using System.Collections;\r
using System.Runtime.Remoting;\r
using System.Runtime.Serialization;\r
+using System.Runtime.Remoting.Messaging;\r
\r
namespace System.Runtime.Serialization.Formatters.Soap {\r
internal sealed class SoapReader {\r
private ISurrogateSelector _surrogateSelector;\r
private XmlTextReader xmlReader;\r
private Hashtable _fieldIndices;\r
+ private long _topObjectId = 1;\r
+ \r
+ class TypeMetadata\r
+ {\r
+ public MemberInfo[] MemberInfos;\r
+ public Hashtable Indices;\r
+ }\r
\r
#endregion\r
\r
#region Public Methods\r
\r
public object Deserialize(Stream inStream, ISoapMessage soapMessage) \r
- {\r
+ {
+ ArrayList headers = null;\r
xmlReader = new XmlTextReader(inStream);\r
xmlReader.WhitespaceHandling = WhitespaceHandling.None;\r
mapper = new SoapTypeMapper(_binder);\r
{\r
// SOAP-ENV:Envelope\r
xmlReader.MoveToContent();\r
- xmlReader.Read();\r
+ xmlReader.ReadStartElement ();
+ xmlReader.MoveToContent();
+
+ // Read headers
+ while (!(xmlReader.NodeType == XmlNodeType.Element && xmlReader.LocalName == "Body" && xmlReader.NamespaceURI == SoapTypeMapper.SoapEnvelopeNamespace))
+ {\r
+ if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.LocalName == "Header" && xmlReader.NamespaceURI == SoapTypeMapper.SoapEnvelopeNamespace)\r
+ {\r
+ if (headers == null) headers = new ArrayList ();\r
+ DeserializeHeaders (headers);\r
+ }\r
+ else
+ xmlReader.Skip ();\r
+ xmlReader.MoveToContent();\r
+ }
+ \r
// SOAP-ENV:Body\r
- xmlReader.Read();\r
+ xmlReader.ReadStartElement();\r
+ xmlReader.MoveToContent();\r
\r
// The root object\r
- if(soapMessage != null)\r
+ if (soapMessage != null)\r
{\r
- if(DeserializeMessage(soapMessage)) \r
- {\r
- RegisterObject(1, soapMessage, null, 0, null, null);\r
+ if (DeserializeMessage (soapMessage)) {\r
+ _topObjectId = NextAvailableId;\r
+ RegisterObject (_topObjectId, soapMessage, null, 0, null, null);\r
}\r
+ xmlReader.MoveToContent();\r
+ \r
+ if (headers != null)\r
+ soapMessage.Headers = (Header[]) headers.ToArray (typeof(Header));\r
}\r
\r
- if(xmlReader.NodeType != XmlNodeType.EndElement)\r
- {\r
- do\r
- {\r
- Deserialize();\r
+ while (xmlReader.NodeType != XmlNodeType.EndElement)\r
+ Deserialize();\r
+ \r
+ // SOAP-ENV:Body\r
+ xmlReader.ReadEndElement ();\r
+ xmlReader.MoveToContent();\r
\r
- }\r
- while(xmlReader.NodeType != XmlNodeType.EndElement); \r
- }\r
+ // SOAP-ENV:Envelope\r
+ xmlReader.ReadEndElement ();\r
}\r
finally \r
{\r
{\r
objMgr.DoFixups();\r
objMgr.RaiseDeserializationEvent();\r
- return objMgr.GetObject(1);\r
+ return objMgr.GetObject(_topObjectId);\r
}\r
}\r
\r
xmlReader.ReadEndElement();\r
RegisterObject(paramValuesId, message.ParamValues, null, 0, null, null);\r
return true;\r
+ }
+\r
+ void DeserializeHeaders (ArrayList headers)\r
+ {\r
+ xmlReader.ReadStartElement ();\r
+ xmlReader.MoveToContent ();\r
+ \r
+ while (xmlReader.NodeType != XmlNodeType.EndElement) \r
+ {\r
+ if (xmlReader.NodeType != XmlNodeType.Element) { xmlReader.Skip(); continue; }\r
+ \r
+ if (xmlReader.GetAttribute ("root", SoapTypeMapper.SoapEncodingNamespace) == "1")\r
+ headers.Add (DeserializeHeader ());\r
+ else\r
+ Deserialize ();\r
+\r
+ xmlReader.MoveToContent ();\r
+ }\r
+ \r
+ xmlReader.ReadEndElement ();\r
+ }
+ \r Header DeserializeHeader ()
+ {
+ Header h = new Header (xmlReader.LocalName, null);
+ h.HeaderNamespace = xmlReader.NamespaceURI;\r
+ h.MustUnderstand = xmlReader.GetAttribute ("mustUnderstand", SoapTypeMapper.SoapEnvelopeNamespace) == "1";\r
+ \r
+ object value;\r
+ long fieldId, fieldHref;\r
+ long idHeader = NextAvailableId;\r
+ FieldInfo fieldInfo = typeof(Header).GetField ("Value");\r
+\r
+ value = DeserializeComponent (null, out fieldId, out fieldHref, idHeader, fieldInfo, null);\r
+ h.Value = value;\r
+\r
+ if(fieldHref != 0 && value == null)\r
+ {\r
+ RecordFixup (idHeader, fieldHref, h, null, null, fieldInfo, null);\r
+ }\r
+ else if(value != null && value.GetType().IsValueType && fieldId != 0)\r
+ {\r
+ RecordFixup (idHeader, fieldId, h, null, null, fieldInfo, null);\r
+ }\r
+ else if(fieldId != 0)\r
+ {\r
+ RegisterObject (fieldId, value, null, idHeader, fieldInfo, null);\r
+ }\r
+ \r
+ RegisterObject (idHeader, h, null, 0, null, null);\r
+ return h;\r
}\r
\r
\r
string elementString = xmlReader.ReadElementString();\r
object obj = SoapTypeMapper.ParseXsdValue (elementString, type);\r
\r
- if(id > 0) \r
+ if(id != 0) \r
RegisterObject(id, obj, info, parentId, parentMemberInfo, indices);\r
\r
return obj;\r
{\r
hasFixup = false;\r
Type currentType = obj.GetType();\r
- MemberInfo[] memberInfos = \r
- FormatterServices.GetSerializableMembers(currentType, _context);\r
- Hashtable indices = (Hashtable) _fieldIndices[currentType];\r
- if(indices == null) \r
- {\r
- indices = new Hashtable();\r
- for(int i = 0; i < memberInfos.Length; i++) \r
- {\r
- indices.Add(memberInfos[i].Name, i);\r
- }\r
- _fieldIndices[currentType] = indices;\r
- }\r
+ TypeMetadata tm = GetTypeMetadata (currentType);\r
\r
int objDepth = xmlReader.Depth;\r
- object[] data = new object[memberInfos.Length];\r
+ object[] data = new object[tm.MemberInfos.Length];\r
xmlReader.Read();\r
- for(int i = 0; i < memberInfos.Length; i++)\r
+ for(int i = 0; i < tm.MemberInfos.Length; i++)\r
{\r
object fieldObject;\r
long fieldId, fieldHref;\r
- int index = (int) indices[xmlReader.LocalName];\r
- FieldInfo fieldInfo = (memberInfos[index]) as FieldInfo;\r
+ int index = (int) tm.Indices[xmlReader.LocalName];\r
+ FieldInfo fieldInfo = (tm.MemberInfos[index]) as FieldInfo;\r
if(fieldInfo == null) continue;\r
\r
fieldObject = \r
}\r
}\r
\r
- FormatterServices.PopulateObjectMembers(obj, memberInfos, data);\r
+ FormatterServices.PopulateObjectMembers (obj, tm.MemberInfos, data);\r
return obj;\r
}\r
\r
}\r
}\r
\r
-\r
+ TypeMetadata GetTypeMetadata (Type type)\r
+ {\r
+ TypeMetadata tm = _fieldIndices[type] as TypeMetadata;\r
+ if (tm != null) return tm;\r
+ \r
+ tm = new TypeMetadata ();\r
+ tm.MemberInfos = FormatterServices.GetSerializableMembers (type, _context);\r
+ \r
+ tm.Indices = new Hashtable();\r
+ for(int i = 0; i < tm.MemberInfos.Length; i++) \r
+ tm.Indices.Add (tm.MemberInfos[i].Name, i);\r
+ \r
+ _fieldIndices[type] = tm;\r
+ return tm;\r
+ }\r
\r
#endregion\r
}\r
using System.Reflection;\r
using System.Collections;\r
using System.Runtime.Remoting;\r
+using System.Runtime.Remoting.Messaging;\r
using System.Runtime.Serialization;\r
using System.Runtime.Serialization.Formatters;\r
using System.Xml;\r
private ObjectIDGenerator idGen = new ObjectIDGenerator();\r
private FormatterAssemblyStyle _assemblyFormat = FormatterAssemblyStyle.Full;\r
private FormatterTypeStyle _typeFormat = FormatterTypeStyle.TypesWhenNeeded;\r
+ private static string defaultMessageNamespace;\r
\r
#endregion\r
\r
\r
static SoapWriter() \r
{\r
-\r
+ defaultMessageNamespace = typeof(SoapWriter).Assembly.GetName().FullName;\r
}\r
\r
#endregion\r
}\r
\r
\r
- internal void Serialize(\r
- object objGraph,\r
- FormatterTypeStyle typeFormat,\r
- FormatterAssemblyStyle assemblyFormat)\r
+ internal void Serialize (object objGraph, Header[] headers, FormatterTypeStyle typeFormat, FormatterAssemblyStyle assemblyFormat)\r
{\r
_typeFormat = typeFormat;\r
_assemblyFormat = assemblyFormat;\r
SoapTypeMapper.SoapEnvelopePrefix,\r
"encodingStyle",\r
SoapTypeMapper.SoapEnvelopeNamespace,\r
- "http://schemas.xmlsoap.org/soap/encoding/");\r
-\r
+ "http://schemas.xmlsoap.org/soap/encoding/");
+
+ ISoapMessage msg = objGraph as ISoapMessage;\r
+ if (msg != null)\r
+ headers = msg.Headers;\r
+ \r
+ if (headers != null && headers.Length > 0)\r
+ {\r
+ _xmlWriter.WriteStartElement (SoapTypeMapper.SoapEnvelopePrefix, "Header", SoapTypeMapper.SoapEnvelopeNamespace);\r
+ foreach (Header h in headers)\r
+ SerializeHeader (h);\r
+ \r
+ WriteObjectQueue ();\r
+ _xmlWriter.WriteEndElement ();\r
+ }\r
+ \r
// The body element\r
_xmlWriter.WriteStartElement(\r
SoapTypeMapper.SoapEnvelopePrefix,\r
\r
bool firstTime = false;\r
\r
- if(objGraph is ISoapMessage)\r
- {\r
- SerializeMessage(objGraph as ISoapMessage);\r
- \r
- }\r
+ if (msg != null)\r
+ SerializeMessage(msg);\r
else\r
_objectQueue.Enqueue(new EnqueuedObject( objGraph, idGen.GetId(objGraph, out firstTime)));\r
\r
+ WriteObjectQueue ();\r
+\r
+ _xmlWriter.WriteFullEndElement(); // the body element\r
+ _xmlWriter.WriteFullEndElement(); // the envelope element\r
+ _xmlWriter.Flush();\r
+ }\r
+ \r
+ private void WriteObjectQueue ()\r
+ {\r
while(_objectQueue.Count > 0) \r
{\r
EnqueuedObject currentEnqueuedObject;\r
\r
if(!currentType.IsValueType) _objectToIdTable[currentObject] = currentEnqueuedObject.Id;\r
\r
- if(currentType.IsArray) \r
- {\r
- SerializeArray((Array) currentObject, currentEnqueuedObject.Id);\r
- }\r
+ if(currentType.IsArray)\r
+ SerializeArray((Array) currentObject, currentEnqueuedObject.Id);\r
else\r
- {\r
SerializeObject(currentObject, currentEnqueuedObject.Id);\r
- }\r
-\r
}\r
-\r
- _xmlWriter.WriteFullEndElement(); // the body element\r
- _xmlWriter.WriteFullEndElement(); // the envelope element\r
- _xmlWriter.Flush();\r
}\r
\r
private void SerializeMessage(ISoapMessage message) \r
{\r
bool firstTime;\r
- _xmlWriter.WriteStartElement("i2", message.MethodName, message.XmlNameSpace);\r
+ string ns = message.XmlNameSpace != null ? message.XmlNameSpace : defaultMessageNamespace;\r
+ \r
+ _xmlWriter.WriteStartElement("i2", message.MethodName, ns);\r
Id(idGen.GetId(message, out firstTime));\r
\r
string[] paramNames = message.ParamNames;\r
\r
\r
_xmlWriter.WriteFullEndElement();\r
+ }
+ \r private void SerializeHeader (Header header)
+ {
+ string ns = header.HeaderNamespace != null ? header.HeaderNamespace : "http://schemas.microsoft.com/clr/soap";
+ _xmlWriter.WriteStartElement ("h4", header.Name, ns);
+ if (header.MustUnderstand)
+ _xmlWriter.WriteAttributeString ("mustUnderstand", SoapTypeMapper.SoapEnvelopeNamespace, "1");\r
+ _xmlWriter.WriteAttributeString ("root", SoapTypeMapper.SoapEncodingNamespace, "1");\r
+ SerializeComponent (header.Value, true);\r
+ _xmlWriter.WriteEndElement();\r
}\r
\r
private void SerializeObject(object currentObject, long currentObjectId) \r
if(currentObjectId > 0)\r
_xmlWriter.WriteFullEndElement();\r
\r
- }\r
-\r
- private void SerializeISerializableObject(\r
+ }
+
+ \r private void SerializeISerializableObject(\r
object currentObject,\r
long currentObjectId,\r
ISerializationSurrogate surrogate)\r