2 // System.ServiceModel.MessageHeader.cs
4 // Author: Duncan Mak (duncan@novell.com)
5 // Atsushi Enomoto (atsushi@ximian.com)
7 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System
.Runtime
.Serialization
;
32 using System
.ServiceModel
;
33 using System
.ServiceModel
.Channels
;
37 namespace System
.ServiceModel
.Channels
39 public abstract class MessageHeader
: MessageHeaderInfo
41 static readonly XmlWriterSettings writer_settings
;
43 static MessageHeader ()
45 writer_settings
= new XmlWriterSettings ();
46 writer_settings
.OmitXmlDeclaration
= true;
47 writer_settings
.Indent
= true;
50 protected MessageHeader () {}
52 static string default_actor
= String
.Empty
;
53 static bool default_is_ref
= false;
54 static bool default_must_understand
= false;
55 static bool default_relay
= false;
57 public static MessageHeader
CreateHeader (string name
, string ns
, object value)
59 return CreateHeader (name
, ns
, value, default_must_understand
);
62 public static MessageHeader
CreateHeader (string name
, string ns
, object value, bool must_understand
)
64 return CreateHeader (name
, ns
, value, must_understand
, default_actor
);
67 public static MessageHeader
CreateHeader (string name
, string ns
, object value, XmlObjectSerializer formatter
)
69 return CreateHeader (name
, ns
, value, formatter
, default_must_understand
,
70 default_actor
, default_relay
);
73 public static MessageHeader
CreateHeader (string name
, string ns
, object value,
74 bool must_understand
, string actor
)
76 return CreateHeader (name
, ns
, value, must_understand
, actor
, default_relay
);
79 public static MessageHeader
CreateHeader (string name
, string ns
, object value, XmlObjectSerializer formatter
,
82 return CreateHeader (name
, ns
, value, formatter
, must_understand
, default_actor
, default_relay
);
85 public static MessageHeader
CreateHeader (string name
, string ns
, object value,
86 bool must_understand
, string actor
, bool relay
)
88 return CreateHeader (name
, ns
, value, new DataContractSerializer (value.GetType ()),
89 must_understand
, actor
, relay
);
92 public static MessageHeader
CreateHeader (string name
, string ns
, object value, XmlObjectSerializer formatter
,
93 bool must_understand
, string actor
)
95 return CreateHeader (name
, ns
, value, formatter
, must_understand
, actor
, default_relay
);
98 public static MessageHeader
CreateHeader (string name
, string ns
, object value, XmlObjectSerializer formatter
,
99 bool must_understand
, string actor
, bool relay
)
101 // FIXME: how to get IsReferenceParameter ?
102 return new DefaultMessageHeader (name
, ns
, value, formatter
, default_is_ref
, must_understand
, actor
, relay
);
105 public virtual bool IsMessageVersionSupported (MessageVersion version
)
107 if (version
.Envelope
== EnvelopeVersion
.Soap12
)
108 if (Actor
== EnvelopeVersion
.Soap11
.NextDestinationActorValue
)
111 if (version
.Envelope
== EnvelopeVersion
.Soap11
)
112 if (Actor
== EnvelopeVersion
.Soap12
.NextDestinationActorValue
||
113 Actor
== EnvelopeVersion
.Soap12UltimateReceiver
)
116 // by default, it's always supported
120 protected abstract void OnWriteHeaderContents (XmlDictionaryWriter writer
, MessageVersion version
);
122 protected virtual void OnWriteStartHeader (XmlDictionaryWriter writer
, MessageVersion version
)
124 var dic
= Constants
.SoapDictionary
;
125 XmlDictionaryString name
, ns
;
126 var prefix
= Namespace
.Length
> 0 ? writer
.LookupPrefix (Namespace
) : String
.Empty
;
127 if (dic
.TryLookup (Name
, out name
) && dic
.TryLookup (Namespace
, out ns
))
128 writer
.WriteStartElement (prefix
, name
, ns
);
130 writer
.WriteStartElement (prefix
, this.Name
, this.Namespace
);
131 WriteHeaderAttributes (writer
, version
);
134 public override string ToString ()
136 StringBuilder sb
= new StringBuilder ();
138 XmlWriter w
= XmlWriter
.Create (sb
, writer_settings
);
140 WriteHeader (w
, MessageVersion
.Default
);
143 return sb
.ToString ();
146 public void WriteHeader (XmlDictionaryWriter writer
, MessageVersion version
)
149 throw new ArgumentNullException ("writer is null.");
152 throw new ArgumentNullException ("version is null.");
154 if (version
.Envelope
== EnvelopeVersion
.None
)
157 WriteStartHeader (writer
, version
);
158 WriteHeaderContents (writer
, version
);
160 writer
.WriteEndElement ();
163 public void WriteHeader (XmlWriter writer
, MessageVersion version
)
165 WriteHeader (XmlDictionaryWriter
.CreateDictionaryWriter (writer
), version
);
168 protected void WriteHeaderAttributes (XmlDictionaryWriter writer
, MessageVersion version
)
170 var dic
= Constants
.SoapDictionary
;
172 writer
.WriteAttributeString ("u", dic
.Add ("Id"), dic
.Add (Constants
.WsuNamespace
), Id
);
173 if (Actor
!= String
.Empty
) {
174 if (version
.Envelope
== EnvelopeVersion
.Soap11
)
175 writer
.WriteAttributeString ("s", dic
.Add ("actor"), dic
.Add (version
.Envelope
.Namespace
), Actor
);
177 if (version
.Envelope
== EnvelopeVersion
.Soap12
)
178 writer
.WriteAttributeString ("s", dic
.Add ("role"), dic
.Add (version
.Envelope
.Namespace
), Actor
);
181 // mustUnderstand is the same across SOAP 1.1 and 1.2
182 if (MustUnderstand
== true)
183 writer
.WriteAttributeString ("s", dic
.Add ("mustUnderstand"), dic
.Add (version
.Envelope
.Namespace
), "1");
185 // relay is only available on SOAP 1.2
186 if (Relay
== true && version
.Envelope
== EnvelopeVersion
.Soap12
)
187 writer
.WriteAttributeString ("s", dic
.Add ("relay"), dic
.Add (version
.Envelope
.Namespace
), "true");
190 public void WriteHeaderContents (XmlDictionaryWriter writer
, MessageVersion version
)
192 this.OnWriteHeaderContents (writer
, version
);
195 public void WriteStartHeader (XmlDictionaryWriter writer
, MessageVersion version
)
197 this.OnWriteStartHeader (writer
, version
);
200 public override string Actor { get { return default_actor; }}
202 public override bool IsReferenceParameter { get { return default_is_ref; }}
204 public override bool MustUnderstand { get { return default_must_understand; }}
206 public override bool Relay { get { return default_relay; }}
208 internal class RawMessageHeader
: MessageHeader
211 bool is_ref
, must_understand
, relay
;
215 string namespace_uri
;
217 public RawMessageHeader (XmlReader reader
, string soap_ns
)
219 Id
= reader
.GetAttribute ("Id", Constants
.WsuNamespace
);
221 string s
= reader
.GetAttribute ("relay", soap_ns
);
222 relay
= s
!= null ? XmlConvert
.ToBoolean (s
) : false;
223 s
= reader
.GetAttribute ("mustUnderstand", soap_ns
);
224 must_understand
= s
!= null ? XmlConvert
.ToBoolean (s
) : false;
225 actor
= reader
.GetAttribute ("actor", soap_ns
) ?? String
.Empty
;
227 s
= reader
.GetAttribute ("IsReferenceParameter", Constants
.WsaNamespace
);
228 is_ref
= s
!= null ? XmlConvert
.ToBoolean (s
) : false;
230 local_name
= reader
.LocalName
;
231 namespace_uri
= reader
.NamespaceURI
;
232 body
= reader
.ReadOuterXml ();
235 public XmlReader
CreateReader ()
237 var reader
= XmlReader
.Create (new StringReader (body
));
238 reader
.MoveToContent ();
242 protected override void OnWriteHeaderContents (
243 XmlDictionaryWriter writer
, MessageVersion version
)
245 var r
= CreateReader ();
247 if (r
.IsEmptyElement
)
248 return; // write nothing
249 for (r
.Read (); r
.NodeType
!= XmlNodeType
.EndElement
;)
250 writer
.WriteNode (r
, false);
253 public override string Actor { get { return actor; }}
255 public override bool IsReferenceParameter { get { return is_ref; }}
257 public override bool MustUnderstand { get { return must_understand; }}
259 public override string Name { get { return local_name; }}
261 public override string Namespace { get { return namespace_uri; }}
263 public override bool Relay { get { return relay; }}
266 internal class DefaultMessageHeader
: MessageHeader
268 string actor
, name
, ns
;
270 XmlObjectSerializer formatter
;
271 bool is_ref
, must_understand
, relay
;
273 internal DefaultMessageHeader (string name
, string ns
, object value, XmlObjectSerializer formatter
,
274 bool isReferenceParameter
,
275 bool mustUnderstand
, string actor
, bool relay
)
280 this.formatter
= formatter
;
281 this.is_ref
= isReferenceParameter
;
282 this.must_understand
= mustUnderstand
;
287 protected override void OnWriteHeaderContents (XmlDictionaryWriter writer
,
288 MessageVersion version
)
290 // FIXME: it's a nasty workaround just to avoid UniqueId output as a string, for bug #577139.
291 if (Value
is UniqueId
)
292 writer
.WriteValue ((UniqueId
) Value
);
294 this.formatter
.WriteObjectContent (writer
, value);
297 public object Value { get { return value; }
}
299 public override string Actor { get { return actor; }}
301 public override bool IsReferenceParameter { get { return is_ref; }}
303 public override bool MustUnderstand { get { return must_understand; }}
305 public override string Name { get { return name; }}
307 public override string Namespace { get { return ns; }}
309 public override bool Relay { get { return relay; }}