MetadataResolver.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Description
  5. {
  6. using System.Collections;
  7. using System.Collections.Generic;
  8. using System.Collections.ObjectModel;
  9. using System.Diagnostics;
  10. using System.Runtime;
  11. using System.Runtime.Diagnostics;
  12. using System.ServiceModel;
  13. using System.ServiceModel.Diagnostics;
  14. using System.Xml;
  15. public static class MetadataResolver
  16. {
  17. public static ServiceEndpointCollection Resolve(Type contract, EndpointAddress address)
  18. {
  19. if (contract == null)
  20. {
  21. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contract");
  22. }
  23. return Resolve(CreateContractCollection(contract), address);
  24. }
  25. public static ServiceEndpointCollection Resolve(IEnumerable<ContractDescription> contracts, EndpointAddress address)
  26. {
  27. return Resolve(contracts, address, new MetadataExchangeClient(address));
  28. }
  29. public static ServiceEndpointCollection Resolve(IEnumerable<ContractDescription> contracts, EndpointAddress address, MetadataExchangeClient client)
  30. {
  31. if (address == null)
  32. {
  33. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
  34. }
  35. if (client == null)
  36. {
  37. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("client");
  38. }
  39. if (contracts == null)
  40. {
  41. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contracts");
  42. }
  43. ValidateContracts(contracts);
  44. MetadataSet metadataSet = client.GetMetadata(address);
  45. return ImportEndpoints(metadataSet, contracts, client);
  46. }
  47. public static ServiceEndpointCollection Resolve(Type contract, Uri address, MetadataExchangeClientMode mode)
  48. {
  49. if (contract == null)
  50. {
  51. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contract");
  52. }
  53. return Resolve(CreateContractCollection(contract), address, mode);
  54. }
  55. public static ServiceEndpointCollection Resolve(IEnumerable<ContractDescription> contracts, Uri address, MetadataExchangeClientMode mode)
  56. {
  57. return Resolve(contracts, address, mode, new MetadataExchangeClient(address, mode));
  58. }
  59. public static ServiceEndpointCollection Resolve(IEnumerable<ContractDescription> contracts, Uri address, MetadataExchangeClientMode mode, MetadataExchangeClient client)
  60. {
  61. if (address == null)
  62. {
  63. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
  64. }
  65. MetadataExchangeClientModeHelper.Validate(mode);
  66. if (client == null)
  67. {
  68. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("client");
  69. }
  70. if (contracts == null)
  71. {
  72. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contracts");
  73. }
  74. ValidateContracts(contracts);
  75. MetadataSet metadataSet = client.GetMetadata(address, mode);
  76. return ImportEndpoints(metadataSet, contracts, client);
  77. }
  78. public static IAsyncResult BeginResolve(Type contract, EndpointAddress address, AsyncCallback callback, object asyncState)
  79. {
  80. if (contract == null)
  81. {
  82. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contract");
  83. }
  84. return BeginResolve(CreateContractCollection(contract), address, callback, asyncState);
  85. }
  86. public static IAsyncResult BeginResolve(IEnumerable<ContractDescription> contracts, EndpointAddress address, AsyncCallback callback, object asyncState)
  87. {
  88. return BeginResolve(contracts, address, new MetadataExchangeClient(address), callback, asyncState);
  89. }
  90. public static IAsyncResult BeginResolve(IEnumerable<ContractDescription> contracts, EndpointAddress address, MetadataExchangeClient client, AsyncCallback callback, object asyncState)
  91. {
  92. if (address == null)
  93. {
  94. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
  95. }
  96. if (client == null)
  97. {
  98. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("client");
  99. }
  100. if (contracts == null)
  101. {
  102. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contracts");
  103. }
  104. ValidateContracts(contracts);
  105. return new AsyncMetadataResolverHelper(address, MetadataExchangeClientMode.MetadataExchange, client, contracts, callback, asyncState);
  106. }
  107. public static IAsyncResult BeginResolve(Type contract, Uri address, MetadataExchangeClientMode mode, AsyncCallback callback, object asyncState)
  108. {
  109. if (contract == null)
  110. {
  111. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contract");
  112. }
  113. return BeginResolve(CreateContractCollection(contract), address, mode, callback, asyncState);
  114. }
  115. public static IAsyncResult BeginResolve(IEnumerable<ContractDescription> contracts, Uri address, MetadataExchangeClientMode mode, AsyncCallback callback, object asyncState)
  116. {
  117. return BeginResolve(contracts, address, mode, new MetadataExchangeClient(address, mode), callback, asyncState);
  118. }
  119. public static IAsyncResult BeginResolve(IEnumerable<ContractDescription> contracts, Uri address, MetadataExchangeClientMode mode, MetadataExchangeClient client,
  120. AsyncCallback callback, object asyncState)
  121. {
  122. if (address == null)
  123. {
  124. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
  125. }
  126. MetadataExchangeClientModeHelper.Validate(mode);
  127. if (client == null)
  128. {
  129. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("client");
  130. }
  131. if (contracts == null)
  132. {
  133. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contracts");
  134. }
  135. ValidateContracts(contracts);
  136. return new AsyncMetadataResolverHelper(new EndpointAddress(address), mode, client, contracts, callback, asyncState);
  137. }
  138. public static ServiceEndpointCollection EndResolve(IAsyncResult result)
  139. {
  140. return AsyncMetadataResolverHelper.EndAsyncCall(result);
  141. }
  142. class AsyncMetadataResolverHelper : AsyncResult
  143. {
  144. MetadataExchangeClient client;
  145. EndpointAddress address;
  146. ServiceEndpointCollection endpointCollection;
  147. MetadataExchangeClientMode mode;
  148. IEnumerable<ContractDescription> knownContracts;
  149. internal AsyncMetadataResolverHelper(EndpointAddress address, MetadataExchangeClientMode mode, MetadataExchangeClient client, IEnumerable<ContractDescription> knownContracts, AsyncCallback callback, object asyncState)
  150. : base(callback, asyncState)
  151. {
  152. this.address = address;
  153. this.client = client;
  154. this.mode = mode;
  155. this.knownContracts = knownContracts;
  156. GetMetadataSetAsync();
  157. }
  158. internal void GetMetadataSetAsync()
  159. {
  160. IAsyncResult result;
  161. if (this.mode == MetadataExchangeClientMode.HttpGet)
  162. {
  163. result = this.client.BeginGetMetadata(this.address.Uri, MetadataExchangeClientMode.HttpGet, Fx.ThunkCallback(new AsyncCallback(this.EndGetMetadataSet)), null);
  164. }
  165. else
  166. {
  167. result = this.client.BeginGetMetadata(this.address, Fx.ThunkCallback(new AsyncCallback(this.EndGetMetadataSet)), null);
  168. }
  169. if (result.CompletedSynchronously)
  170. {
  171. HandleResult(result);
  172. this.Complete(true);
  173. }
  174. }
  175. internal void EndGetMetadataSet(IAsyncResult result)
  176. {
  177. if (result.CompletedSynchronously)
  178. return;
  179. Exception exception = null;
  180. try
  181. {
  182. HandleResult(result);
  183. }
  184. catch (Exception e)
  185. {
  186. if (Fx.IsFatal(e))
  187. throw;
  188. exception = e;
  189. }
  190. this.Complete(false, exception);
  191. }
  192. private void HandleResult(IAsyncResult result)
  193. {
  194. MetadataSet metadataSet = this.client.EndGetMetadata(result);
  195. endpointCollection = ImportEndpoints(metadataSet, knownContracts, this.client);
  196. }
  197. internal static ServiceEndpointCollection EndAsyncCall(IAsyncResult result)
  198. {
  199. AsyncMetadataResolverHelper helper = AsyncResult.End<AsyncMetadataResolverHelper>(result);
  200. return helper.endpointCollection;
  201. }
  202. }
  203. private static ServiceEndpointCollection ImportEndpoints(MetadataSet metadataSet, IEnumerable<ContractDescription> contracts, MetadataExchangeClient client)
  204. {
  205. ServiceEndpointCollection endpoints = new ServiceEndpointCollection();
  206. WsdlImporter importer = new WsdlImporter(metadataSet);
  207. // remember the original proxy so user doesn't need to set it again
  208. importer.State.Add(MetadataExchangeClient.MetadataExchangeClientKey, client);
  209. foreach (ContractDescription cd in contracts)
  210. {
  211. importer.KnownContracts.Add(WsdlExporter.WsdlNamingHelper.GetPortTypeQName(cd), cd);
  212. }
  213. foreach (ContractDescription cd in contracts)
  214. {
  215. ServiceEndpointCollection contractEndpoints;
  216. contractEndpoints = importer.ImportEndpoints(cd);
  217. foreach (ServiceEndpoint se in contractEndpoints)
  218. {
  219. endpoints.Add(se);
  220. }
  221. }
  222. //Trace all warnings and errors
  223. if (importer.Errors.Count > 0)
  224. {
  225. TraceWsdlImportErrors(importer);
  226. }
  227. return endpoints;
  228. }
  229. static void TraceWsdlImportErrors(WsdlImporter importer)
  230. {
  231. foreach (MetadataConversionError error in importer.Errors)
  232. {
  233. if (DiagnosticUtility.ShouldTraceWarning)
  234. {
  235. Hashtable h = new Hashtable(2)
  236. {
  237. { "IsWarning", error.IsWarning },
  238. { "Message", error.Message }
  239. };
  240. TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.WsmexNonCriticalWsdlExportError,
  241. SR.GetString(SR.TraceCodeWsmexNonCriticalWsdlExportError), new DictionaryTraceRecord(h), null, null);
  242. }
  243. }
  244. }
  245. private static void ValidateContracts(IEnumerable<ContractDescription> contracts)
  246. {
  247. bool isEmpty = true;
  248. Collection<XmlQualifiedName> qnames = new Collection<XmlQualifiedName>();
  249. foreach (ContractDescription cd in contracts)
  250. {
  251. isEmpty = false;
  252. if (cd == null)
  253. {
  254. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxMetadataResolverKnownContractsCannotContainNull));
  255. }
  256. XmlQualifiedName qname = WsdlExporter.WsdlNamingHelper.GetPortTypeQName(cd);
  257. if (qnames.Contains(qname))
  258. {
  259. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxMetadataResolverKnownContractsUniqueQNames, qname.Name, qname.Namespace));
  260. }
  261. qnames.Add(qname);
  262. }
  263. if (isEmpty)
  264. {
  265. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxMetadataResolverKnownContractsArgumentCannotBeEmpty));
  266. }
  267. }
  268. private static Collection<ContractDescription> CreateContractCollection(Type contract)
  269. {
  270. Collection<ContractDescription> contracts = new Collection<ContractDescription>();
  271. contracts.Add(ContractDescription.GetContract(contract));
  272. return contracts;
  273. }
  274. }
  275. }