MessageEncodingBindingElementImporter.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.ServiceModel.Channels
  5. {
  6. using System.Collections.Generic;
  7. using System.ServiceModel.Description;
  8. using System.Xml;
  9. using System.Xml.Schema;
  10. using System.Web.Services.Description;
  11. public class MessageEncodingBindingElementImporter : IWsdlImportExtension, IPolicyImportExtension
  12. {
  13. void IWsdlImportExtension.BeforeImport(ServiceDescriptionCollection wsdlDocuments, XmlSchemaSet xmlSchemas, ICollection<XmlElement> policy)
  14. {
  15. }
  16. void IWsdlImportExtension.ImportContract(WsdlImporter importer, WsdlContractConversionContext context) { }
  17. void IWsdlImportExtension.ImportEndpoint(WsdlImporter importer, WsdlEndpointConversionContext context)
  18. {
  19. if (context == null)
  20. {
  21. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
  22. }
  23. #pragma warning suppress 56506 // [....], these properties cannot be null in this context
  24. if (context.Endpoint.Binding == null)
  25. {
  26. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context.Endpoint.Binding");
  27. }
  28. BindingElementCollection bindingElements = GetBindingElements(context);
  29. MessageEncodingBindingElement messageEncodingBindingElement = bindingElements.Find<MessageEncodingBindingElement>();
  30. TextMessageEncodingBindingElement textEncodingBindingElement = messageEncodingBindingElement as TextMessageEncodingBindingElement;
  31. if (messageEncodingBindingElement != null)
  32. {
  33. Type elementType = messageEncodingBindingElement.GetType();
  34. if (elementType != typeof(TextMessageEncodingBindingElement)
  35. && elementType != typeof(BinaryMessageEncodingBindingElement)
  36. && elementType != typeof(MtomMessageEncodingBindingElement))
  37. return;
  38. }
  39. EnsureMessageEncoding(context, messageEncodingBindingElement);
  40. foreach (OperationBinding wsdlOperationBinding in context.WsdlBinding.Operations)
  41. {
  42. OperationDescription operation = context.GetOperationDescription(wsdlOperationBinding);
  43. for (int i = 0; i < operation.Messages.Count; i++)
  44. {
  45. MessageDescription message = operation.Messages[i];
  46. MessageBinding wsdlMessageBinding = context.GetMessageBinding(message);
  47. ImportMessageSoapAction(context.ContractConversionContext, message, wsdlMessageBinding, i != 0 /*isResponse*/);
  48. }
  49. foreach (FaultDescription fault in operation.Faults)
  50. {
  51. FaultBinding wsdlFaultBinding = context.GetFaultBinding(fault);
  52. if (wsdlFaultBinding != null)
  53. {
  54. ImportFaultSoapAction(context.ContractConversionContext, fault, wsdlFaultBinding);
  55. }
  56. }
  57. }
  58. }
  59. static void ImportFaultSoapAction(WsdlContractConversionContext contractContext, FaultDescription fault, FaultBinding wsdlFaultBinding)
  60. {
  61. string soapAction = SoapHelper.ReadSoapAction(wsdlFaultBinding.OperationBinding);
  62. if (contractContext != null)
  63. {
  64. OperationFault wsdlOperationFault = contractContext.GetOperationFault(fault);
  65. string wsaAction = WsdlImporter.WSAddressingHelper.FindWsaActionAttribute(wsdlOperationFault);
  66. if (wsaAction == null && soapAction != null)
  67. fault.Action = soapAction;
  68. //
  69. }
  70. else
  71. {
  72. //
  73. }
  74. }
  75. static void ImportMessageSoapAction(WsdlContractConversionContext contractContext, MessageDescription message, MessageBinding wsdlMessageBinding, bool isResponse)
  76. {
  77. string soapAction = SoapHelper.ReadSoapAction(wsdlMessageBinding.OperationBinding);
  78. if (contractContext != null)
  79. {
  80. OperationMessage wsdlOperationMessage = contractContext.GetOperationMessage(message);
  81. string wsaAction = WsdlImporter.WSAddressingHelper.FindWsaActionAttribute(wsdlOperationMessage);
  82. if (wsaAction == null && soapAction != null)
  83. {
  84. if (isResponse)
  85. {
  86. message.Action = "*";
  87. }
  88. else
  89. {
  90. message.Action = soapAction;
  91. }
  92. }
  93. //
  94. }
  95. else
  96. {
  97. //
  98. }
  99. }
  100. static void EnsureMessageEncoding(WsdlEndpointConversionContext context, MessageEncodingBindingElement encodingBindingElement)
  101. {
  102. EnvelopeVersion soapVersion = SoapHelper.GetSoapVersion(context.WsdlBinding);
  103. AddressingVersion addressingVersion;
  104. if (encodingBindingElement == null)
  105. {
  106. encodingBindingElement = new TextMessageEncodingBindingElement();
  107. ConvertToCustomBinding(context).Elements.Add(encodingBindingElement);
  108. addressingVersion = AddressingVersion.None;
  109. }
  110. else
  111. {
  112. if (soapVersion == EnvelopeVersion.None)
  113. addressingVersion = AddressingVersion.None;
  114. else
  115. addressingVersion = encodingBindingElement.MessageVersion.Addressing;
  116. }
  117. MessageVersion newMessageVersion = MessageVersion.CreateVersion(soapVersion, addressingVersion);
  118. if (!encodingBindingElement.MessageVersion.IsMatch(newMessageVersion))
  119. {
  120. ConvertToCustomBinding(context).Elements.Find<MessageEncodingBindingElement>().MessageVersion
  121. = MessageVersion.CreateVersion(soapVersion, addressingVersion);
  122. }
  123. }
  124. static BindingElementCollection GetBindingElements(WsdlEndpointConversionContext context)
  125. {
  126. Binding binding = context.Endpoint.Binding;
  127. BindingElementCollection elements = binding is CustomBinding ? ((CustomBinding)binding).Elements : binding.CreateBindingElements();
  128. return elements;
  129. }
  130. static CustomBinding ConvertToCustomBinding(WsdlEndpointConversionContext context)
  131. {
  132. CustomBinding customBinding = context.Endpoint.Binding as CustomBinding;
  133. if (customBinding == null)
  134. {
  135. customBinding = new CustomBinding(context.Endpoint.Binding);
  136. context.Endpoint.Binding = customBinding;
  137. }
  138. return customBinding;
  139. }
  140. void IPolicyImportExtension.ImportPolicy(MetadataImporter importer, PolicyConversionContext context)
  141. {
  142. if (importer == null)
  143. {
  144. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("importer");
  145. }
  146. if (context == null)
  147. {
  148. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
  149. }
  150. ImportPolicyInternal(context);
  151. }
  152. void ImportPolicyInternal(PolicyConversionContext context)
  153. {
  154. ICollection<XmlElement> assertions = context.GetBindingAssertions();
  155. XmlElement encodingAssertion;
  156. MessageEncodingBindingElement encodingBindingElement;
  157. encodingBindingElement = CreateEncodingBindingElement(context.GetBindingAssertions(), out encodingAssertion);
  158. AddressingVersion addressingVersion = WsdlImporter.WSAddressingHelper.FindAddressingVersion(context);
  159. ApplyAddressingVersion(encodingBindingElement, addressingVersion);
  160. #pragma warning suppress 56506
  161. context.BindingElements.Add(encodingBindingElement);
  162. }
  163. static void ApplyAddressingVersion(MessageEncodingBindingElement encodingBindingElement, AddressingVersion addressingVersion)
  164. {
  165. EnvelopeVersion defaultEnvelopeVersion = encodingBindingElement.MessageVersion.Envelope;
  166. if (defaultEnvelopeVersion == EnvelopeVersion.None
  167. && addressingVersion != AddressingVersion.None)
  168. {
  169. // The default envelope version is None which incompatible with the
  170. // addressing version.
  171. // We replace it with soap12. This will be updated at wsdl import time if necessary.
  172. encodingBindingElement.MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, addressingVersion);
  173. }
  174. else
  175. {
  176. encodingBindingElement.MessageVersion = MessageVersion.CreateVersion(defaultEnvelopeVersion, addressingVersion);
  177. }
  178. }
  179. MessageEncodingBindingElement CreateEncodingBindingElement(ICollection<XmlElement> assertions, out XmlElement encodingAssertion)
  180. {
  181. encodingAssertion = null;
  182. foreach (XmlElement assertion in assertions)
  183. {
  184. switch (assertion.NamespaceURI)
  185. {
  186. case MessageEncodingPolicyConstants.BinaryEncodingNamespace:
  187. if (assertion.LocalName == MessageEncodingPolicyConstants.BinaryEncodingName)
  188. {
  189. encodingAssertion = assertion;
  190. assertions.Remove(encodingAssertion);
  191. return new BinaryMessageEncodingBindingElement();
  192. }
  193. break;
  194. case MessageEncodingPolicyConstants.OptimizedMimeSerializationNamespace:
  195. if (assertion.LocalName == MessageEncodingPolicyConstants.MtomEncodingName)
  196. {
  197. encodingAssertion = assertion;
  198. assertions.Remove(encodingAssertion);
  199. return new MtomMessageEncodingBindingElement();
  200. }
  201. break;
  202. }
  203. }
  204. return new TextMessageEncodingBindingElement();
  205. }
  206. }
  207. static class MessageEncodingPolicyConstants
  208. {
  209. public const string BinaryEncodingName = "BinaryEncoding";
  210. public const string BinaryEncodingNamespace = "http://schemas.microsoft.com/ws/06/2004/mspolicy/netbinary1";
  211. public const string BinaryEncodingPrefix = "msb";
  212. public const string OptimizedMimeSerializationNamespace = "http://schemas.xmlsoap.org/ws/2004/09/policy/optimizedmimeserialization";
  213. public const string OptimizedMimeSerializationPrefix = "wsoma";
  214. public const string MtomEncodingName = "OptimizedMimeSerialization";
  215. }
  216. }