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;
56 static Type [] knownTypes = new Type [1] {typeof (EndpointAddress10)};
58 public static MessageHeader CreateHeader (string name, string ns, object value)
60 return CreateHeader (name, ns, value, default_must_understand);
63 public static MessageHeader CreateHeader (string name, string ns, object value, bool must_understand)
65 return CreateHeader (name, ns, value, must_understand, default_actor);
68 public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer formatter)
70 return CreateHeader (name, ns, value, formatter, default_must_understand,
71 default_actor, default_relay);
74 public static MessageHeader CreateHeader (string name, string ns, object value,
75 bool must_understand, string actor)
77 return CreateHeader (name, ns, value, must_understand, actor, default_relay);
80 public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer formatter,
83 return CreateHeader (name, ns, value, formatter, must_understand, default_actor, default_relay);
86 public static MessageHeader CreateHeader (string name, string ns, object value,
87 bool must_understand, string actor, bool relay)
89 return CreateHeader (name, ns, value, new DataContractSerializer (value.GetType (), knownTypes),
90 must_understand, actor, relay);
93 public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer formatter,
94 bool must_understand, string actor)
96 return CreateHeader (name, ns, value, formatter, must_understand, actor, default_relay);
99 public static MessageHeader CreateHeader (string name, string ns, object value, XmlObjectSerializer formatter,
100 bool must_understand, string actor, bool relay)
102 // FIXME: how to get IsReferenceParameter ?
103 return new DefaultMessageHeader (name, ns, value, formatter, default_is_ref, must_understand, actor, relay);
106 public virtual bool IsMessageVersionSupported (MessageVersion version)
108 if (version.Envelope == EnvelopeVersion.Soap12)
109 if (Actor == EnvelopeVersion.Soap11.NextDestinationActorValue)
112 if (version.Envelope == EnvelopeVersion.Soap11)
113 if (Actor == EnvelopeVersion.Soap12.NextDestinationActorValue ||
114 Actor == EnvelopeVersion.Soap12UltimateReceiver)
117 // by default, it's always supported
121 protected abstract void OnWriteHeaderContents (XmlDictionaryWriter writer, MessageVersion version);
123 protected virtual void OnWriteStartHeader (XmlDictionaryWriter writer, MessageVersion version)
125 writer.WriteStartElement (this.Name, this.Namespace);
126 WriteHeaderAttributes (writer, version);
129 public override string ToString ()
131 StringBuilder sb = new StringBuilder ();
133 XmlWriter w = XmlWriter.Create (sb, writer_settings);
135 WriteHeader (w, MessageVersion.Default);
138 return sb.ToString ();
141 public void WriteHeader (XmlDictionaryWriter writer, MessageVersion version)
144 throw new ArgumentNullException ("writer is null.");
147 throw new ArgumentNullException ("version is null.");
149 if (version.Envelope == EnvelopeVersion.None)
152 WriteStartHeader (writer, version);
153 WriteHeaderContents (writer, version);
155 writer.WriteEndElement ();
158 public void WriteHeader (XmlWriter writer, MessageVersion version)
160 WriteHeader (XmlDictionaryWriter.CreateDictionaryWriter (writer), version);
163 protected void WriteHeaderAttributes (XmlDictionaryWriter writer, MessageVersion version)
166 writer.WriteAttributeString ("u", "Id", Constants.WsuNamespace, Id);
167 if (Actor != String.Empty) {
168 if (version.Envelope == EnvelopeVersion.Soap11)
169 writer.WriteAttributeString ("s", "actor", version.Envelope.Namespace, Actor);
171 if (version.Envelope == EnvelopeVersion.Soap12)
172 writer.WriteAttributeString ("s", "role", version.Envelope.Namespace, Actor);
175 // mustUnderstand is the same across SOAP 1.1 and 1.2
176 if (MustUnderstand == true)
177 writer.WriteAttributeString ("s", "mustUnderstand", version.Envelope.Namespace, "1");
179 // relay is only available on SOAP 1.2
180 if (Relay == true && version.Envelope == EnvelopeVersion.Soap12)
181 writer.WriteAttributeString ("s", "relay", version.Envelope.Namespace, "true");
184 public void WriteHeaderContents (XmlDictionaryWriter writer, MessageVersion version)
186 this.OnWriteHeaderContents (writer, version);
189 public void WriteStartHeader (XmlDictionaryWriter writer, MessageVersion version)
191 this.OnWriteStartHeader (writer, version);
194 public override string Actor { get { return default_actor; }}
196 public override bool IsReferenceParameter { get { return default_is_ref; }}
198 public override bool MustUnderstand { get { return default_must_understand; }}
200 public override bool Relay { get { return default_relay; }}
202 internal class RawMessageHeader : MessageHeader
205 bool is_ref, must_understand, relay;
209 string namespace_uri;
211 public RawMessageHeader (XmlReader reader, string soap_ns)
213 Id = reader.GetAttribute ("Id", Constants.WsuNamespace);
215 // FIXME: fill is_ref
216 string s = reader.GetAttribute ("relay", soap_ns);
217 relay = s != null ? XmlConvert.ToBoolean (s) : false;
218 s = reader.GetAttribute ("mustUnderstand", soap_ns);
219 must_understand = s != null ? XmlConvert.ToBoolean (s) : false;
220 actor = reader.GetAttribute ("actor", soap_ns) ?? String.Empty;
221 local_name = reader.LocalName;
222 namespace_uri = reader.NamespaceURI;
223 body = reader.ReadOuterXml ();
226 public XmlReader CreateReader ()
228 var reader = XmlReader.Create (new StringReader (body));
229 reader.MoveToContent ();
233 protected override void OnWriteHeaderContents (
234 XmlDictionaryWriter writer, MessageVersion version)
236 var r = CreateReader ();
238 if (r.IsEmptyElement)
239 return; // write nothing
240 for (r.Read (); r.NodeType != XmlNodeType.EndElement;)
241 writer.WriteNode (r, false);
244 public override string Actor { get { return actor; }}
246 public override bool IsReferenceParameter { get { return is_ref; }}
248 public override bool MustUnderstand { get { return must_understand; }}
250 public override string Name { get { return local_name; }}
252 public override string Namespace { get { return namespace_uri; }}
254 public override bool Relay { get { return relay; }}
257 internal class DefaultMessageHeader : MessageHeader
259 string actor, name, ns;
261 XmlObjectSerializer formatter;
262 bool is_ref, must_understand, relay;
264 internal DefaultMessageHeader (string name, string ns, object value, XmlObjectSerializer formatter,
265 bool isReferenceParameter,
266 bool mustUnderstand, string actor, bool relay)
271 this.formatter = formatter;
272 this.is_ref = isReferenceParameter;
273 this.must_understand = mustUnderstand;
278 protected override void OnWriteHeaderContents (XmlDictionaryWriter writer,
279 MessageVersion version)
281 if (value is EndpointAddress)
282 ((EndpointAddress) value).WriteTo (version.Addressing, writer, name, ns);
284 this.formatter.WriteObjectContent (writer, value);
287 public override string Actor { get { return actor; }}
289 public override bool IsReferenceParameter { get { return is_ref; }}
291 public override bool MustUnderstand { get { return must_understand; }}
293 public override string Name { get { return name; }}
295 public override string Namespace { get { return ns; }}
297 public override bool Relay { get { return relay; }}