Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.ServiceModel / System / ServiceModel / Channels / MessageFault.cs
1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4
5
6 namespace System.ServiceModel.Channels
7 {
8     using System.Xml;
9     using System.ServiceModel;
10     using System.ServiceModel.Description;
11     using System.Text;
12     using System.Collections.Generic;
13     using System.Runtime.Serialization;
14     using System.ServiceModel.Diagnostics;
15     using System.ServiceModel.Dispatcher;
16     using System.Globalization;
17
18     public abstract class MessageFault
19     {
20         static MessageFault defaultMessageFault;
21
22         public static MessageFault CreateFault(FaultCode code, string reason)
23         {
24             return CreateFault(code, new FaultReason(reason));
25         }
26
27         public static MessageFault CreateFault(FaultCode code, FaultReason reason)
28         {
29             return CreateFault(code, reason, null, null, "", "");
30         }
31
32         public static MessageFault CreateFault(FaultCode code, FaultReason reason, object detail)
33         {
34             return CreateFault(code, reason, detail, DataContractSerializerDefaults.CreateSerializer(
35                 (detail == null ? typeof(object) : detail.GetType()), int.MaxValue/*maxItems*/), "", "");
36         }
37
38         public static MessageFault CreateFault(FaultCode code, FaultReason reason, object detail, XmlObjectSerializer serializer)
39         {
40             return CreateFault(code, reason, detail, serializer, "", "");
41         }
42
43         public static MessageFault CreateFault(FaultCode code, FaultReason reason, object detail, XmlObjectSerializer serializer, string actor)
44         {
45             if (serializer == null)
46                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serializer"));
47             return CreateFault(code, reason, detail, serializer, actor, actor);
48         }
49
50         public static MessageFault CreateFault(FaultCode code, FaultReason reason, object detail, XmlObjectSerializer serializer, string actor, string node)
51         {
52             if (code == null)
53                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("code"));
54             if (reason == null)
55                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("reason"));
56             if (actor == null)
57                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("actor"));
58             if (node == null)
59                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("node"));
60             return new XmlObjectSerializerFault(code, reason, detail, serializer, actor, node);
61         }
62
63         public static MessageFault CreateFault(Message message, int maxBufferSize)
64         {
65             if (message == null)
66                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("message"));
67             XmlDictionaryReader reader = message.GetReaderAtBodyContents();
68             using (reader)
69             {
70                 try
71                 {
72 #pragma warning suppress 56506 // Microsoft, Message.Version can never be null
73                     EnvelopeVersion envelopeVersion = message.Version.Envelope;
74                     MessageFault fault;
75                     if (envelopeVersion == EnvelopeVersion.Soap12)
76                     {
77                         fault = ReceivedFault.CreateFault12(reader, maxBufferSize);
78                     }
79                     else if (envelopeVersion == EnvelopeVersion.Soap11)
80                     {
81                         fault = ReceivedFault.CreateFault11(reader, maxBufferSize);
82                     }
83                     else if (envelopeVersion == EnvelopeVersion.None)
84                     {
85                         fault = ReceivedFault.CreateFaultNone(reader, maxBufferSize);
86                     }
87                     else
88                     {
89                         throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.EnvelopeVersionUnknown, envelopeVersion.ToString())), message);
90                     }
91                     message.ReadFromBodyContentsToEnd(reader);
92                     return fault;
93                 }
94                 catch (InvalidOperationException e)
95                 {
96                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
97                         SR.GetString(SR.SFxErrorDeserializingFault), e));
98                 }
99                 catch (FormatException e)
100                 {
101                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
102                         SR.GetString(SR.SFxErrorDeserializingFault), e));
103                 }
104                 catch (XmlException e)
105                 {
106                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
107                         SR.GetString(SR.SFxErrorDeserializingFault), e));
108                 }
109             }
110         }
111
112         internal static MessageFault Default
113         {
114             get
115             {
116                 if (defaultMessageFault == null)
117                 {
118                     defaultMessageFault = MessageFault.CreateFault(new FaultCode("Default"), new FaultReason("", CultureInfo.CurrentCulture));
119                 }
120                 return defaultMessageFault;
121             }
122         }
123
124         public virtual string Actor
125         {
126             get
127             {
128                 return "";
129             }
130         }
131
132         public abstract FaultCode Code { get; }
133
134         public bool IsMustUnderstandFault
135         {
136             get
137             {
138                 FaultCode code = this.Code;
139                 if (String.Compare(code.Name, MessageStrings.MustUnderstandFault, StringComparison.Ordinal) != 0)
140                 {
141                     return false;
142                 }
143
144                 if ((String.Compare(code.Namespace, EnvelopeVersion.Soap11.Namespace, StringComparison.Ordinal) != 0) &&
145                     (String.Compare(code.Namespace, EnvelopeVersion.Soap12.Namespace, StringComparison.Ordinal) != 0))
146                 {
147                     return false;
148                 }
149
150                 return true;
151             }
152         }
153
154         public virtual string Node
155         {
156             get
157             {
158                 return "";
159             }
160         }
161
162         public abstract bool HasDetail { get; }
163
164         public abstract FaultReason Reason { get; }
165
166         public T GetDetail<T>()
167         {
168             return GetDetail<T>(DataContractSerializerDefaults.CreateSerializer(typeof(T), int.MaxValue/*maxItems*/));
169         }
170
171         public T GetDetail<T>(XmlObjectSerializer serializer)
172         {
173             if (serializer == null)
174                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serializer"));
175             XmlDictionaryReader reader = GetReaderAtDetailContents();
176             T value = (T)serializer.ReadObject(reader);
177             if (!reader.EOF)
178             {
179                 reader.MoveToContent();
180                 if (reader.NodeType != XmlNodeType.EndElement && !reader.EOF)
181                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.ExtraContentIsPresentInFaultDetail)));
182             }
183             return value;
184         }
185
186         public XmlDictionaryReader GetReaderAtDetailContents()
187         {
188             if (!HasDetail)
189                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FaultDoesNotHaveAnyDetail)));
190             return OnGetReaderAtDetailContents();
191         }
192
193         protected virtual void OnWriteDetail(XmlDictionaryWriter writer, EnvelopeVersion version)
194         {
195             OnWriteStartDetail(writer, version);
196             OnWriteDetailContents(writer);
197             writer.WriteEndElement();
198         }
199
200         protected virtual void OnWriteStartDetail(XmlDictionaryWriter writer, EnvelopeVersion version)
201         {
202             if (version == EnvelopeVersion.Soap12)
203                 writer.WriteStartElement(XD.Message12Dictionary.FaultDetail, XD.Message12Dictionary.Namespace);
204             else if (version == EnvelopeVersion.Soap11)
205                 writer.WriteStartElement(XD.Message11Dictionary.FaultDetail, XD.Message11Dictionary.FaultNamespace);
206             else
207                 writer.WriteStartElement(XD.Message12Dictionary.FaultDetail, XD.MessageDictionary.Namespace);
208         }
209
210         protected abstract void OnWriteDetailContents(XmlDictionaryWriter writer);
211
212         protected virtual XmlDictionaryReader OnGetReaderAtDetailContents()
213         {
214             XmlBuffer detailBuffer = new XmlBuffer(int.MaxValue);
215             XmlDictionaryWriter writer = detailBuffer.OpenSection(XmlDictionaryReaderQuotas.Max);
216             OnWriteDetail(writer, EnvelopeVersion.Soap12);  // Wrap in soap 1.2 by default
217             detailBuffer.CloseSection();
218             detailBuffer.Close();
219             XmlDictionaryReader reader = detailBuffer.GetReader(0);
220             reader.Read(); // Skip the detail element
221             return reader;
222         }
223
224         public static bool WasHeaderNotUnderstood(MessageHeaders headers, string name, string ns)
225         {
226             if (headers == null)
227             {
228                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("headers");
229             }
230
231             for (int i = 0; i < headers.Count; i++)
232             {
233                 MessageHeaderInfo headerInfo = headers[i];
234                 if ((String.Compare(headerInfo.Name, Message12Strings.NotUnderstood, StringComparison.Ordinal) == 0) &&
235                     (String.Compare(headerInfo.Namespace, Message12Strings.Namespace, StringComparison.Ordinal) == 0))
236                 {
237                     using (XmlDictionaryReader reader = headers.GetReaderAtHeader(i))
238                     {
239                         reader.MoveToAttribute(Message12Strings.QName, Message12Strings.Namespace);
240
241                         string actualName;
242                         string actualNamespace;
243                         reader.ReadContentAsQualifiedName(out actualName, out actualNamespace);
244
245                         if ((actualName != null) &&
246                             (actualNamespace != null) &&
247                             (String.Compare(name, actualName, StringComparison.Ordinal) == 0) &&
248                             (String.Compare(ns, actualNamespace, StringComparison.Ordinal) == 0))
249                         {
250                             return true;
251                         }
252                     }
253                 }
254             }
255
256             return false;
257         }
258
259         public void WriteTo(XmlWriter writer, EnvelopeVersion version)
260         {
261             WriteTo(XmlDictionaryWriter.CreateDictionaryWriter(writer), version);
262         }
263
264         public void WriteTo(XmlDictionaryWriter writer, EnvelopeVersion version)
265         {
266             if (writer == null)
267             {
268                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
269             }
270
271             if (version == null)
272             {
273                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("version");
274             }
275
276             if (version == EnvelopeVersion.Soap12)
277             {
278                 WriteTo12(writer);
279             }
280             else if (version == EnvelopeVersion.Soap11)
281             {
282                 WriteTo11(writer);
283             }
284             else if (version == EnvelopeVersion.None)
285             {
286                 WriteToNone(writer);
287             }
288             else
289             {
290                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.EnvelopeVersionUnknown, version.ToString())));
291             }
292         }
293
294         void WriteToNone(XmlDictionaryWriter writer)
295         {
296             WriteTo12Driver(writer, EnvelopeVersion.None);
297         }
298
299         void WriteTo12Driver(XmlDictionaryWriter writer, EnvelopeVersion version)
300         {
301             writer.WriteStartElement(XD.MessageDictionary.Fault, version.DictionaryNamespace);
302             writer.WriteStartElement(XD.Message12Dictionary.FaultCode, version.DictionaryNamespace);
303             WriteFaultCode12Driver(writer, Code, version);
304             writer.WriteEndElement();
305             writer.WriteStartElement(XD.Message12Dictionary.FaultReason, version.DictionaryNamespace);
306             FaultReason reason = Reason;
307             for (int i = 0; i < reason.Translations.Count; i++)
308             {
309                 FaultReasonText text = reason.Translations[i];
310                 writer.WriteStartElement(XD.Message12Dictionary.FaultText, version.DictionaryNamespace);
311                 writer.WriteAttributeString("xml", "lang", XmlUtil.XmlNs, text.XmlLang);
312                 writer.WriteString(text.Text);
313                 writer.WriteEndElement();
314             }
315             writer.WriteEndElement();
316             if (Node.Length > 0)
317                 writer.WriteElementString(XD.Message12Dictionary.FaultNode, version.DictionaryNamespace, Node);
318             if (Actor.Length > 0)
319                 writer.WriteElementString(XD.Message12Dictionary.FaultRole, version.DictionaryNamespace, Actor);
320             if (HasDetail)
321             {
322                 OnWriteDetail(writer, version);
323             }
324             writer.WriteEndElement();
325         }
326
327         void WriteFaultCode12Driver(XmlDictionaryWriter writer, FaultCode faultCode, EnvelopeVersion version)
328         {
329             writer.WriteStartElement(XD.Message12Dictionary.FaultValue, version.DictionaryNamespace);
330             string name;
331             if (faultCode.IsSenderFault)
332                 name = version.SenderFaultName;
333             else if (faultCode.IsReceiverFault)
334                 name = version.ReceiverFaultName;
335             else
336                 name = faultCode.Name;
337             string ns;
338             if (faultCode.IsPredefinedFault)
339                 ns = version.Namespace;
340             else
341                 ns = faultCode.Namespace;
342             string prefix = writer.LookupPrefix(ns);
343             if (prefix == null)
344                 writer.WriteAttributeString("xmlns", "a", XmlUtil.XmlNsNs, ns);
345             writer.WriteQualifiedName(name, ns);
346             writer.WriteEndElement();
347
348             if (faultCode.SubCode != null)
349             {
350                 writer.WriteStartElement(XD.Message12Dictionary.FaultSubcode, version.DictionaryNamespace);
351                 WriteFaultCode12Driver(writer, faultCode.SubCode, version);
352                 writer.WriteEndElement();
353             }
354         }
355
356         void WriteTo12(XmlDictionaryWriter writer)
357         {
358             WriteTo12Driver(writer, EnvelopeVersion.Soap12);
359         }
360
361         void WriteTo11(XmlDictionaryWriter writer)
362         {
363             writer.WriteStartElement(XD.MessageDictionary.Fault, XD.Message11Dictionary.Namespace);
364             writer.WriteStartElement(XD.Message11Dictionary.FaultCode, XD.Message11Dictionary.FaultNamespace);
365
366             FaultCode faultCode = Code;
367             if (faultCode.SubCode != null)
368                 faultCode = faultCode.SubCode;
369
370             string name;
371             if (faultCode.IsSenderFault)
372                 name = "Client";
373             else if (faultCode.IsReceiverFault)
374                 name = "Server";
375             else
376                 name = faultCode.Name;
377             string ns;
378             if (faultCode.IsPredefinedFault)
379                 ns = Message11Strings.Namespace;
380             else
381                 ns = faultCode.Namespace;
382             string prefix = writer.LookupPrefix(ns);
383             if (prefix == null)
384                 writer.WriteAttributeString("xmlns", "a", XmlUtil.XmlNsNs, ns);
385             writer.WriteQualifiedName(name, ns);
386             writer.WriteEndElement();
387             FaultReasonText translation = Reason.Translations[0];
388             writer.WriteStartElement(XD.Message11Dictionary.FaultString, XD.Message11Dictionary.FaultNamespace);
389             if (translation.XmlLang.Length > 0)
390                 writer.WriteAttributeString("xml", "lang", XmlUtil.XmlNs, translation.XmlLang);
391             writer.WriteString(translation.Text);
392             writer.WriteEndElement();
393             if (Actor.Length > 0)
394                 writer.WriteElementString(XD.Message11Dictionary.FaultActor, XD.Message11Dictionary.FaultNamespace, Actor);
395             if (HasDetail)
396             {
397                 OnWriteDetail(writer, EnvelopeVersion.Soap11);
398             }
399             writer.WriteEndElement();
400         }
401     }
402
403     class XmlObjectSerializerFault : MessageFault
404     {
405         FaultCode code;
406         FaultReason reason;
407         string actor;
408         string node;
409         object detail;
410         XmlObjectSerializer serializer;
411
412         public XmlObjectSerializerFault(FaultCode code, FaultReason reason, object detail, XmlObjectSerializer serializer, string actor, string node)
413         {
414             this.code = code;
415             this.reason = reason;
416             this.detail = detail;
417             this.serializer = serializer;
418             this.actor = actor;
419             this.node = node;
420         }
421
422         public override string Actor
423         {
424             get
425             {
426                 return actor;
427             }
428         }
429
430         public override FaultCode Code
431         {
432             get
433             {
434                 return code;
435             }
436         }
437
438         public override bool HasDetail
439         {
440             get
441             {
442                 return serializer != null;
443             }
444         }
445
446         public override string Node
447         {
448             get
449             {
450                 return node;
451             }
452         }
453
454         public override FaultReason Reason
455         {
456             get
457             {
458                 return reason;
459             }
460         }
461
462         object ThisLock
463         {
464             get
465             {
466                 return code;
467             }
468         }
469
470         protected override void OnWriteDetailContents(XmlDictionaryWriter writer)
471         {
472             if (serializer != null)
473             {
474                 lock (ThisLock)
475                 {
476                     serializer.WriteObject(writer, detail);
477                 }
478             }
479         }
480     }
481
482     class ReceivedFault : MessageFault
483     {
484         FaultCode code;
485         FaultReason reason;
486         string actor;
487         string node;
488         XmlBuffer detail;
489         bool hasDetail;
490         EnvelopeVersion receivedVersion;
491
492         ReceivedFault(FaultCode code, FaultReason reason, string actor, string node, XmlBuffer detail, EnvelopeVersion version)
493         {
494             this.code = code;
495             this.reason = reason;
496             this.actor = actor;
497             this.node = node;
498             this.receivedVersion = version;
499             this.hasDetail = InferHasDetail(detail);
500             this.detail = this.hasDetail ? detail : null;
501         }
502
503         public override string Actor
504         {
505             get
506             {
507                 return actor;
508             }
509         }
510
511         public override FaultCode Code
512         {
513             get
514             {
515                 return code;
516             }
517         }
518
519         public override bool HasDetail
520         {
521             get
522             {
523                 return hasDetail;
524             }
525         }
526
527         public override string Node
528         {
529             get
530             {
531                 return node;
532             }
533         }
534
535         public override FaultReason Reason
536         {
537             get
538             {
539                 return reason;
540             }
541         }
542
543         bool InferHasDetail(XmlBuffer detail)
544         {
545             bool hasDetail = false;
546             if (detail != null)
547             {
548                 XmlDictionaryReader reader = detail.GetReader(0);
549                 if (!reader.IsEmptyElement && reader.Read()) // check if the detail element contains data
550                     hasDetail = (reader.MoveToContent() != XmlNodeType.EndElement);
551                 reader.Close();
552             }
553             return hasDetail;
554         }
555
556         protected override void OnWriteDetail(XmlDictionaryWriter writer, EnvelopeVersion version)
557         {
558             using (XmlReader r = detail.GetReader(0))
559             {
560                 // Start the element
561                 base.OnWriteStartDetail(writer, version);
562
563                 // Copy the attributes
564                 while (r.MoveToNextAttribute())
565                 {
566                     if (ShouldWriteDetailAttribute(version, r.Prefix, r.LocalName, r.Value))
567                     {
568                         writer.WriteAttributeString(r.Prefix, r.LocalName, r.NamespaceURI, r.Value);
569                     }
570                 }
571                 r.MoveToElement();
572
573                 r.Read();
574
575                 // Copy the contents
576                 while (r.NodeType != XmlNodeType.EndElement)
577                     writer.WriteNode(r, false);
578
579                 // End the element
580                 writer.WriteEndElement();
581             }
582         }
583
584         protected override void OnWriteStartDetail(XmlDictionaryWriter writer, EnvelopeVersion version)
585         {
586             using (XmlReader r = detail.GetReader(0))
587             {
588                 // Start the element
589                 base.OnWriteStartDetail(writer, version);
590
591                 // Copy the attributes
592                 while (r.MoveToNextAttribute())
593                 {
594                     if (ShouldWriteDetailAttribute(version, r.Prefix, r.LocalName, r.Value))
595                     {
596                         writer.WriteAttributeString(r.Prefix, r.LocalName, r.NamespaceURI, r.Value);
597                     }
598                 }
599             }
600         }
601
602         protected override void OnWriteDetailContents(XmlDictionaryWriter writer)
603         {
604             using (XmlReader r = detail.GetReader(0))
605             {
606                 r.Read();
607                 while (r.NodeType != XmlNodeType.EndElement)
608                     writer.WriteNode(r, false);
609             }
610         }
611
612         protected override XmlDictionaryReader OnGetReaderAtDetailContents()
613         {
614             XmlDictionaryReader reader = detail.GetReader(0);
615             reader.Read(); // Skip the detail element
616             return reader;
617         }
618
619         bool ShouldWriteDetailAttribute(EnvelopeVersion targetVersion, string prefix, string localName, string attributeValue)
620         {
621             // Handle fault detail version conversion from Soap12 to Soap11 -- scope tightly to only conversion from Soap12 -> Soap11
622             // SOAP 1.1 specifications allow an arbitrary element within <fault>, hence: 
623             // transform this IFF the SOAP namespace specified will affect the namespace of the <detail> element, 
624             // AND the namespace specified is exactly the Soap12 Namespace. 
625             bool shouldSkip = this.receivedVersion == EnvelopeVersion.Soap12    // original incoming version
626                                 && targetVersion == EnvelopeVersion.Soap11      // version to serialize to
627                                 && string.IsNullOrEmpty(prefix)                 // attribute prefix
628                                 && localName == "xmlns"                         // only transform namespace attributes, don't care about others
629                                 && attributeValue == XD.Message12Dictionary.Namespace.Value;
630
631             return !shouldSkip;
632         }
633
634         public static ReceivedFault CreateFaultNone(XmlDictionaryReader reader, int maxBufferSize)
635         {
636             return CreateFault12Driver(reader, maxBufferSize, EnvelopeVersion.None);
637         }
638
639         static ReceivedFault CreateFault12Driver(XmlDictionaryReader reader, int maxBufferSize, EnvelopeVersion version)
640         {
641             reader.ReadStartElement(XD.MessageDictionary.Fault, version.DictionaryNamespace);
642             reader.ReadStartElement(XD.Message12Dictionary.FaultCode, version.DictionaryNamespace);
643             FaultCode code = ReadFaultCode12Driver(reader, version);
644             reader.ReadEndElement();
645             List<FaultReasonText> translations = new List<FaultReasonText>();
646             if (reader.IsEmptyElement)
647             {
648                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.AtLeastOneFaultReasonMustBeSpecified)));
649             }
650             else
651             {
652                 reader.ReadStartElement(XD.Message12Dictionary.FaultReason, version.DictionaryNamespace);
653                 while (reader.IsStartElement(XD.Message12Dictionary.FaultText, version.DictionaryNamespace))
654                     translations.Add(ReadTranslation12(reader));
655                 reader.ReadEndElement();
656             }
657
658             string actor = "";
659             string node = "";
660             if (reader.IsStartElement(XD.Message12Dictionary.FaultNode, version.DictionaryNamespace))
661                 node = reader.ReadElementContentAsString();
662             if (reader.IsStartElement(XD.Message12Dictionary.FaultRole, version.DictionaryNamespace))
663                 actor = reader.ReadElementContentAsString();
664             XmlBuffer detail = null;
665             if (reader.IsStartElement(XD.Message12Dictionary.FaultDetail, version.DictionaryNamespace))
666             {
667                 detail = new XmlBuffer(maxBufferSize);
668                 XmlDictionaryWriter writer = detail.OpenSection(reader.Quotas);
669                 writer.WriteNode(reader, false);
670                 detail.CloseSection();
671                 detail.Close();
672             }
673             reader.ReadEndElement();
674             FaultReason reason = new FaultReason(translations);
675             return new ReceivedFault(code, reason, actor, node, detail, version);
676         }
677
678         static FaultCode ReadFaultCode12Driver(XmlDictionaryReader reader, EnvelopeVersion version)
679         {
680             string localName;
681             string ns;
682             FaultCode subCode = null;
683             reader.ReadStartElement(XD.Message12Dictionary.FaultValue, version.DictionaryNamespace);
684             XmlUtil.ReadContentAsQName(reader, out localName, out ns);
685             reader.ReadEndElement();
686             if (reader.IsStartElement(XD.Message12Dictionary.FaultSubcode, version.DictionaryNamespace))
687             {
688                 reader.ReadStartElement();
689                 subCode = ReadFaultCode12Driver(reader, version);
690                 reader.ReadEndElement();
691                 return new FaultCode(localName, ns, subCode);
692             }
693             return new FaultCode(localName, ns);
694         }
695
696         public static ReceivedFault CreateFault12(XmlDictionaryReader reader, int maxBufferSize)
697         {
698             return CreateFault12Driver(reader, maxBufferSize, EnvelopeVersion.Soap12);
699         }
700
701         static FaultReasonText ReadTranslation12(XmlDictionaryReader reader)
702         {
703             string xmlLang = XmlUtil.GetXmlLangAttribute(reader);
704             string text = reader.ReadElementContentAsString();
705             return new FaultReasonText(text, xmlLang);
706         }
707
708         public static ReceivedFault CreateFault11(XmlDictionaryReader reader, int maxBufferSize)
709         {
710             reader.ReadStartElement(XD.MessageDictionary.Fault, XD.Message11Dictionary.Namespace);
711             string ns;
712             string name;
713             reader.ReadStartElement(XD.Message11Dictionary.FaultCode, XD.Message11Dictionary.FaultNamespace);
714             XmlUtil.ReadContentAsQName(reader, out name, out ns);
715             FaultCode code = new FaultCode(name, ns);
716             reader.ReadEndElement();
717
718             string xmlLang = reader.XmlLang;
719             reader.MoveToContent();  // Don't do IsStartElement.  FaultString is required, so let the reader throw.
720             string text = reader.ReadElementContentAsString(XD.Message11Dictionary.FaultString.Value, XD.Message11Dictionary.FaultNamespace.Value);
721             FaultReasonText translation = new FaultReasonText(text, xmlLang);
722
723             string actor = "";
724             if (reader.IsStartElement(XD.Message11Dictionary.FaultActor, XD.Message11Dictionary.FaultNamespace))
725                 actor = reader.ReadElementContentAsString();
726             XmlBuffer detail = null;
727             if (reader.IsStartElement(XD.Message11Dictionary.FaultDetail, XD.Message11Dictionary.FaultNamespace))
728             {
729                 detail = new XmlBuffer(maxBufferSize);
730                 XmlDictionaryWriter writer = detail.OpenSection(reader.Quotas);
731                 writer.WriteNode(reader, false);
732                 detail.CloseSection();
733                 detail.Close();
734             }
735             reader.ReadEndElement();
736             FaultReason reason = new FaultReason(translation);
737             return new ReceivedFault(code, reason, actor, actor, detail, EnvelopeVersion.Soap11);
738         }
739     }
740 }