2
0

MessageFault.cs 28 KB

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