SoapProtocolImporter.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. //
  2. // System.Web.Services.Description.SoapProtocolImporter.cs
  3. //
  4. // Author:
  5. // Tim Coleman ([email protected])
  6. // Lluis Sanchez Gual ([email protected])
  7. //
  8. // Copyright (C) Tim Coleman, 2002
  9. //
  10. //
  11. // Permission is hereby granted, free of charge, to any person obtaining
  12. // a copy of this software and associated documentation files (the
  13. // "Software"), to deal in the Software without restriction, including
  14. // without limitation the rights to use, copy, modify, merge, publish,
  15. // distribute, sublicense, and/or sell copies of the Software, and to
  16. // permit persons to whom the Software is furnished to do so, subject to
  17. // the following conditions:
  18. //
  19. // The above copyright notice and this permission notice shall be
  20. // included in all copies or substantial portions of the Software.
  21. //
  22. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29. //
  30. using System.CodeDom;
  31. using System.Web.Services;
  32. using System.Web.Services.Protocols;
  33. using System.Web.Services.Configuration;
  34. using System.Xml;
  35. using System.Xml.Schema;
  36. using System.Xml.Serialization;
  37. using System.Configuration;
  38. using System.Collections;
  39. namespace System.Web.Services.Description {
  40. public class SoapProtocolImporter : ProtocolImporter {
  41. #region Fields
  42. SoapBinding soapBinding;
  43. SoapCodeExporter soapExporter;
  44. SoapSchemaImporter soapImporter;
  45. XmlCodeExporter xmlExporter;
  46. XmlSchemaImporter xmlImporter;
  47. CodeIdentifiers memberIds;
  48. ArrayList extensionImporters;
  49. Hashtable headerVariables;
  50. XmlSchemas xmlSchemas;
  51. XmlSchemas soapSchemas;
  52. #endregion // Fields
  53. #region Constructors
  54. public SoapProtocolImporter ()
  55. {
  56. extensionImporters = ExtensionManager.BuildExtensionImporters ();
  57. }
  58. void SetBinding (SoapBinding soapBinding)
  59. {
  60. this.soapBinding = soapBinding;
  61. }
  62. #endregion // Constructors
  63. #region Properties
  64. public override string ProtocolName {
  65. get { return "Soap"; }
  66. }
  67. public SoapBinding SoapBinding {
  68. get { return soapBinding; }
  69. }
  70. public SoapCodeExporter SoapExporter {
  71. get { return soapExporter; }
  72. }
  73. public SoapSchemaImporter SoapImporter {
  74. get { return soapImporter; }
  75. }
  76. public XmlCodeExporter XmlExporter {
  77. get { return xmlExporter; }
  78. }
  79. public XmlSchemaImporter XmlImporter {
  80. get { return xmlImporter; }
  81. }
  82. #endregion // Properties
  83. #region Methods
  84. protected override CodeTypeDeclaration BeginClass ()
  85. {
  86. soapBinding = (SoapBinding) Binding.Extensions.Find (typeof(SoapBinding));
  87. CodeTypeDeclaration codeClass = new CodeTypeDeclaration (ClassName);
  88. string location = null;
  89. SoapAddressBinding sab = (SoapAddressBinding) Port.Extensions.Find (typeof(SoapAddressBinding));
  90. if (sab != null) location = sab.Location;
  91. string url = GetServiceUrl (location);
  92. if (Style == ServiceDescriptionImportStyle.Client) {
  93. CodeTypeReference ctr = new CodeTypeReference ("System.Web.Services.Protocols.SoapHttpClientProtocol");
  94. codeClass.BaseTypes.Add (ctr);
  95. }
  96. else {
  97. CodeTypeReference ctr = new CodeTypeReference ("System.Web.Services.WebService");
  98. codeClass.BaseTypes.Add (ctr);
  99. CodeAttributeDeclaration attws = new CodeAttributeDeclaration ("System.Web.Services.WebServiceAttribute");
  100. attws.Arguments.Add (GetArg ("Namespace", Port.Binding.Namespace));
  101. AddCustomAttribute (codeClass, attws, true);
  102. }
  103. CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Web.Services.WebServiceBinding");
  104. att.Arguments.Add (GetArg ("Name", Port.Name));
  105. att.Arguments.Add (GetArg ("Namespace", Port.Binding.Namespace));
  106. AddCustomAttribute (codeClass, att, true);
  107. if (Style == ServiceDescriptionImportStyle.Client) {
  108. CodeConstructor cc = new CodeConstructor ();
  109. cc.Attributes = MemberAttributes.Public;
  110. CodeExpression ce = new CodeFieldReferenceExpression (new CodeThisReferenceExpression(), "Url");
  111. CodeAssignStatement cas = new CodeAssignStatement (ce, new CodePrimitiveExpression (url));
  112. cc.Statements.Add (cas);
  113. codeClass.Members.Add (cc);
  114. }
  115. memberIds = new CodeIdentifiers ();
  116. headerVariables = new Hashtable ();
  117. return codeClass;
  118. }
  119. protected override void BeginNamespace ()
  120. {
  121. #if NET_2_0
  122. xmlImporter = new XmlSchemaImporter (LiteralSchemas, base.CodeGenerationOptions, base.CodeGenerator, base.ImportContext);
  123. soapImporter = new SoapSchemaImporter (EncodedSchemas, base.CodeGenerationOptions, base.CodeGenerator, base.ImportContext);
  124. xmlExporter = new XmlCodeExporter (CodeNamespace, null, base.CodeGenerator, base.CodeGenerationOptions, null);
  125. soapExporter = new SoapCodeExporter (CodeNamespace, null, base.CodeGenerator, base.CodeGenerationOptions, null);
  126. #else
  127. xmlImporter = new XmlSchemaImporter (LiteralSchemas, ClassNames);
  128. soapImporter = new SoapSchemaImporter (EncodedSchemas, ClassNames);
  129. xmlExporter = new XmlCodeExporter (CodeNamespace, null);
  130. soapExporter = new SoapCodeExporter (CodeNamespace, null);
  131. #endif
  132. }
  133. protected override void EndClass ()
  134. {
  135. SoapTransportImporter transportImporter = SoapTransportImporter.FindTransportImporter (soapBinding.Transport);
  136. if (transportImporter == null) throw new InvalidOperationException ("Transport '" + soapBinding.Transport + "' not supported");
  137. transportImporter.ImportContext = this;
  138. transportImporter.ImportClass ();
  139. if (xmlExporter.IncludeMetadata.Count > 0 || soapExporter.IncludeMetadata.Count > 0)
  140. {
  141. if (CodeTypeDeclaration.CustomAttributes == null)
  142. CodeTypeDeclaration.CustomAttributes = new CodeAttributeDeclarationCollection ();
  143. CodeTypeDeclaration.CustomAttributes.AddRange (xmlExporter.IncludeMetadata);
  144. CodeTypeDeclaration.CustomAttributes.AddRange (soapExporter.IncludeMetadata);
  145. }
  146. }
  147. protected override void EndNamespace ()
  148. {
  149. }
  150. protected override bool IsBindingSupported ()
  151. {
  152. return Binding.Extensions.Find (typeof(SoapBinding)) != null;
  153. }
  154. [MonoTODO]
  155. protected override bool IsOperationFlowSupported (OperationFlow flow)
  156. {
  157. throw new NotImplementedException ();
  158. }
  159. [MonoTODO]
  160. protected virtual bool IsSoapEncodingPresent (string uriList)
  161. {
  162. throw new NotImplementedException ();
  163. }
  164. protected override CodeMemberMethod GenerateMethod ()
  165. {
  166. try
  167. {
  168. SoapOperationBinding soapOper = OperationBinding.Extensions.Find (typeof (SoapOperationBinding)) as SoapOperationBinding;
  169. if (soapOper == null) throw new InvalidOperationException ("Soap operation binding not found");
  170. SoapBindingStyle style = soapOper.Style != SoapBindingStyle.Default ? soapOper.Style : soapBinding.Style;
  171. SoapBodyBinding isbb = null;
  172. XmlMembersMapping inputMembers = null;
  173. isbb = OperationBinding.Input.Extensions.Find (typeof(SoapBodyBinding)) as SoapBodyBinding;
  174. if (isbb == null) throw new InvalidOperationException ("Soap body binding not found");
  175. inputMembers = ImportMembersMapping (InputMessage, isbb, style, false);
  176. if (inputMembers == null) throw new InvalidOperationException ("Input message not declared");
  177. // If OperationBinding.Output is null, it is an OneWay operation
  178. SoapBodyBinding osbb = null;
  179. XmlMembersMapping outputMembers = null;
  180. if (OperationBinding.Output != null) {
  181. osbb = OperationBinding.Output.Extensions.Find (typeof(SoapBodyBinding)) as SoapBodyBinding;
  182. if (osbb == null) throw new InvalidOperationException ("Soap body binding not found");
  183. outputMembers = ImportMembersMapping (OutputMessage, osbb, style, true);
  184. if (outputMembers == null) throw new InvalidOperationException ("Output message not declared");
  185. }
  186. CodeMemberMethod met = GenerateMethod (memberIds, soapOper, isbb, inputMembers, outputMembers);
  187. if (isbb.Use == SoapBindingUse.Literal)
  188. xmlExporter.ExportMembersMapping (inputMembers);
  189. else
  190. soapExporter.ExportMembersMapping (inputMembers);
  191. if (osbb != null) {
  192. if (osbb.Use == SoapBindingUse.Literal)
  193. xmlExporter.ExportMembersMapping (outputMembers);
  194. else
  195. soapExporter.ExportMembersMapping (outputMembers);
  196. }
  197. foreach (SoapExtensionImporter eximporter in extensionImporters)
  198. {
  199. eximporter.ImportContext = this;
  200. eximporter.ImportMethod (met.CustomAttributes);
  201. }
  202. return met;
  203. }
  204. catch (InvalidOperationException ex)
  205. {
  206. UnsupportedOperationBindingWarning (ex.Message);
  207. return null;
  208. }
  209. }
  210. XmlMembersMapping ImportMembersMapping (Message msg, SoapBodyBinding sbb, SoapBindingStyle style, bool output)
  211. {
  212. string elemName = Operation.Name;
  213. if (output) elemName += "Response";
  214. if (msg.Parts.Count == 1 && msg.Parts[0].Name == "parameters")
  215. {
  216. // Wrapped parameter style
  217. MessagePart part = msg.Parts[0];
  218. if (sbb.Use == SoapBindingUse.Encoded)
  219. {
  220. SoapSchemaMember ssm = new SoapSchemaMember ();
  221. ssm.MemberName = part.Name;
  222. ssm.MemberType = part.Type;
  223. return soapImporter.ImportMembersMapping (elemName, part.Type.Namespace, ssm);
  224. }
  225. else
  226. return xmlImporter.ImportMembersMapping (part.Element);
  227. }
  228. else
  229. {
  230. if (sbb.Use == SoapBindingUse.Encoded)
  231. {
  232. SoapSchemaMember[] mems = new SoapSchemaMember [msg.Parts.Count];
  233. for (int n=0; n<mems.Length; n++)
  234. {
  235. SoapSchemaMember mem = new SoapSchemaMember();
  236. mem.MemberName = msg.Parts[n].Name;
  237. mem.MemberType = msg.Parts[n].Type;
  238. mems[n] = mem;
  239. }
  240. // Rpc messages always have a wrapping element
  241. if (style == SoapBindingStyle.Rpc)
  242. return soapImporter.ImportMembersMapping (elemName, sbb.Namespace, mems, true);
  243. else
  244. return soapImporter.ImportMembersMapping ("", "", mems, false);
  245. }
  246. else
  247. {
  248. if (style == SoapBindingStyle.Rpc)
  249. throw new InvalidOperationException ("The combination of style=rpc with use=literal is not supported");
  250. if (msg.Parts.Count == 1 && msg.Parts[0].Type != XmlQualifiedName.Empty)
  251. return xmlImporter.ImportAnyType (msg.Parts[0].Type, null);
  252. else
  253. {
  254. XmlQualifiedName[] pnames = new XmlQualifiedName [msg.Parts.Count];
  255. for (int n=0; n<pnames.Length; n++)
  256. pnames[n] = msg.Parts[n].Element;
  257. return xmlImporter.ImportMembersMapping (pnames);
  258. }
  259. }
  260. }
  261. }
  262. CodeMemberMethod GenerateMethod (CodeIdentifiers memberIds, SoapOperationBinding soapOper, SoapBodyBinding bodyBinding, XmlMembersMapping inputMembers, XmlMembersMapping outputMembers)
  263. {
  264. CodeIdentifiers pids = new CodeIdentifiers ();
  265. CodeMemberMethod method = new CodeMemberMethod ();
  266. CodeMemberMethod methodBegin = new CodeMemberMethod ();
  267. CodeMemberMethod methodEnd = new CodeMemberMethod ();
  268. method.Attributes = MemberAttributes.Public | MemberAttributes.Final;
  269. methodBegin.Attributes = MemberAttributes.Public | MemberAttributes.Final;
  270. methodEnd.Attributes = MemberAttributes.Public | MemberAttributes.Final;
  271. SoapBindingStyle style = soapOper.Style != SoapBindingStyle.Default ? soapOper.Style : soapBinding.Style;
  272. // Find unique names for temporary variables
  273. for (int n=0; n<inputMembers.Count; n++)
  274. pids.AddUnique (inputMembers[n].MemberName, inputMembers[n]);
  275. if (outputMembers != null)
  276. for (int n=0; n<outputMembers.Count; n++)
  277. pids.AddUnique (outputMembers[n].MemberName, outputMembers[n]);
  278. string varAsyncResult = pids.AddUnique ("asyncResult","asyncResult");
  279. string varResults = pids.AddUnique ("results","results");
  280. string varCallback = pids.AddUnique ("callback","callback");
  281. string varAsyncState = pids.AddUnique ("asyncState","asyncState");
  282. string messageName = memberIds.AddUnique(CodeIdentifier.MakeValid(Operation.Name),method);
  283. method.Name = CodeIdentifier.MakeValid(Operation.Name);
  284. if (method.Name == ClassName) method.Name += "1";
  285. methodBegin.Name = memberIds.AddUnique(CodeIdentifier.MakeValid("Begin" + method.Name),method);
  286. methodEnd.Name = memberIds.AddUnique(CodeIdentifier.MakeValid("End" + method.Name),method);
  287. method.ReturnType = new CodeTypeReference (typeof(void));
  288. methodEnd.ReturnType = new CodeTypeReference (typeof(void));
  289. methodEnd.Parameters.Add (new CodeParameterDeclarationExpression (typeof (IAsyncResult),varAsyncResult));
  290. CodeExpression[] paramArray = new CodeExpression [inputMembers.Count];
  291. CodeParameterDeclarationExpression[] outParams = new CodeParameterDeclarationExpression [outputMembers != null ? outputMembers.Count : 0];
  292. for (int n=0; n<inputMembers.Count; n++)
  293. {
  294. CodeParameterDeclarationExpression param = GenerateParameter (inputMembers[n], FieldDirection.In);
  295. method.Parameters.Add (param);
  296. GenerateMemberAttributes (inputMembers, inputMembers[n], bodyBinding.Use, param);
  297. methodBegin.Parameters.Add (GenerateParameter (inputMembers[n], FieldDirection.In));
  298. paramArray [n] = new CodeVariableReferenceExpression (param.Name);
  299. }
  300. if (outputMembers != null)
  301. {
  302. bool hasReturn = false;
  303. for (int n=0; n<outputMembers.Count; n++)
  304. {
  305. CodeParameterDeclarationExpression cpd = GenerateParameter (outputMembers[n], FieldDirection.Out);
  306. outParams [n] = cpd;
  307. bool found = false;
  308. foreach (CodeParameterDeclarationExpression ip in method.Parameters)
  309. {
  310. if (ip.Name == cpd.Name && ip.Type.BaseType == cpd.Type.BaseType) {
  311. ip.Direction = FieldDirection.Ref;
  312. methodEnd.Parameters.Add (GenerateParameter (outputMembers[n], FieldDirection.Out));
  313. found = true;
  314. break;
  315. }
  316. }
  317. if (found) continue;
  318. if (!hasReturn)
  319. {
  320. hasReturn = true;
  321. method.ReturnType = cpd.Type;
  322. methodEnd.ReturnType = cpd.Type;
  323. GenerateReturnAttributes (outputMembers, outputMembers[n], bodyBinding.Use, method);
  324. outParams [n] = null;
  325. continue;
  326. }
  327. method.Parameters.Add (cpd);
  328. GenerateMemberAttributes (outputMembers, outputMembers[n], bodyBinding.Use, cpd);
  329. methodEnd.Parameters.Add (GenerateParameter (outputMembers[n], FieldDirection.Out));
  330. }
  331. }
  332. methodBegin.Parameters.Add (new CodeParameterDeclarationExpression (typeof (AsyncCallback),varCallback));
  333. methodBegin.Parameters.Add (new CodeParameterDeclarationExpression (typeof (object),varAsyncState));
  334. methodBegin.ReturnType = new CodeTypeReference (typeof(IAsyncResult));
  335. // Array of input parameters
  336. CodeArrayCreateExpression methodParams;
  337. if (paramArray.Length > 0)
  338. methodParams = new CodeArrayCreateExpression (typeof(object), paramArray);
  339. else
  340. methodParams = new CodeArrayCreateExpression (typeof(object), 0);
  341. // Assignment of output parameters
  342. CodeStatementCollection outAssign = new CodeStatementCollection ();
  343. CodeVariableReferenceExpression arrVar = new CodeVariableReferenceExpression (varResults);
  344. for (int n=0; n<outParams.Length; n++)
  345. {
  346. CodeExpression index = new CodePrimitiveExpression (n);
  347. if (outParams[n] == null)
  348. {
  349. CodeExpression res = new CodeCastExpression (method.ReturnType, new CodeArrayIndexerExpression (arrVar, index));
  350. outAssign.Add (new CodeMethodReturnStatement (res));
  351. }
  352. else
  353. {
  354. CodeExpression res = new CodeCastExpression (outParams[n].Type, new CodeArrayIndexerExpression (arrVar, index));
  355. CodeExpression var = new CodeVariableReferenceExpression (outParams[n].Name);
  356. outAssign.Insert (0, new CodeAssignStatement (var, res));
  357. }
  358. }
  359. if (Style == ServiceDescriptionImportStyle.Client)
  360. {
  361. // Invoke call
  362. CodeThisReferenceExpression ethis = new CodeThisReferenceExpression();
  363. CodePrimitiveExpression varMsgName = new CodePrimitiveExpression (messageName);
  364. CodeMethodInvokeExpression inv;
  365. CodeVariableDeclarationStatement dec;
  366. inv = new CodeMethodInvokeExpression (ethis, "Invoke", varMsgName, methodParams);
  367. if (outputMembers != null && outputMembers.Count > 0)
  368. {
  369. dec = new CodeVariableDeclarationStatement (typeof(object[]), varResults, inv);
  370. method.Statements.Add (dec);
  371. method.Statements.AddRange (outAssign);
  372. }
  373. else
  374. method.Statements.Add (inv);
  375. // Begin Invoke Call
  376. CodeExpression expCallb = new CodeVariableReferenceExpression (varCallback);
  377. CodeExpression expAsyncs = new CodeVariableReferenceExpression (varAsyncState);
  378. inv = new CodeMethodInvokeExpression (ethis, "BeginInvoke", varMsgName, methodParams, expCallb, expAsyncs);
  379. methodBegin.Statements.Add (new CodeMethodReturnStatement (inv));
  380. // End Invoke call
  381. CodeExpression varAsyncr = new CodeVariableReferenceExpression (varAsyncResult);
  382. inv = new CodeMethodInvokeExpression (ethis, "EndInvoke", varAsyncr);
  383. if (outputMembers != null && outputMembers.Count > 0)
  384. {
  385. dec = new CodeVariableDeclarationStatement (typeof(object[]), varResults, inv);
  386. methodEnd.Statements.Add (dec);
  387. methodEnd.Statements.AddRange (outAssign);
  388. }
  389. else
  390. methodEnd.Statements.Add (inv);
  391. }
  392. else {
  393. method.Attributes = MemberAttributes.Public | MemberAttributes.Abstract;
  394. }
  395. // Attributes
  396. ImportHeaders (method);
  397. CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Web.Services.WebMethodAttribute");
  398. if (messageName != method.Name) att.Arguments.Add (GetArg ("MessageName",messageName));
  399. AddCustomAttribute (method, att, (Style == ServiceDescriptionImportStyle.Server));
  400. if (style == SoapBindingStyle.Rpc)
  401. {
  402. att = new CodeAttributeDeclaration ("System.Web.Services.Protocols.SoapRpcMethodAttribute");
  403. att.Arguments.Add (GetArg (soapOper.SoapAction));
  404. if (inputMembers.ElementName != method.Name) att.Arguments.Add (GetArg ("RequestElementName", inputMembers.ElementName));
  405. if (outputMembers != null && outputMembers.ElementName != (method.Name + "Response")) att.Arguments.Add (GetArg ("ResponseElementName", outputMembers.ElementName));
  406. att.Arguments.Add (GetArg ("RequestNamespace", inputMembers.Namespace));
  407. if (outputMembers != null) att.Arguments.Add (GetArg ("ResponseNamespace", outputMembers.Namespace));
  408. if (outputMembers == null) att.Arguments.Add (GetArg ("OneWay", true));
  409. }
  410. else
  411. {
  412. if (outputMembers != null && (inputMembers.ElementName == "" && outputMembers.ElementName != "" ||
  413. inputMembers.ElementName != "" && outputMembers.ElementName == ""))
  414. throw new InvalidOperationException ("Parameter style is not the same for the input message and output message");
  415. att = new CodeAttributeDeclaration ("System.Web.Services.Protocols.SoapDocumentMethodAttribute");
  416. att.Arguments.Add (GetArg (soapOper.SoapAction));
  417. if (inputMembers.ElementName != "") {
  418. if (inputMembers.ElementName != method.Name) att.Arguments.Add (GetArg ("RequestElementName", inputMembers.ElementName));
  419. if (outputMembers != null && outputMembers.ElementName != (method.Name + "Response")) att.Arguments.Add (GetArg ("ResponseElementName", outputMembers.ElementName));
  420. att.Arguments.Add (GetArg ("RequestNamespace", inputMembers.Namespace));
  421. if (outputMembers != null) att.Arguments.Add (GetArg ("ResponseNamespace", outputMembers.Namespace));
  422. att.Arguments.Add (GetEnumArg ("ParameterStyle", "System.Web.Services.Protocols.SoapParameterStyle", "Wrapped"));
  423. }
  424. else
  425. att.Arguments.Add (GetEnumArg ("ParameterStyle", "System.Web.Services.Protocols.SoapParameterStyle", "Bare"));
  426. if (outputMembers == null) att.Arguments.Add (GetArg ("OneWay", true));
  427. att.Arguments.Add (GetEnumArg ("Use", "System.Web.Services.Description.SoapBindingUse", bodyBinding.Use.ToString()));
  428. }
  429. AddCustomAttribute (method, att, true);
  430. CodeTypeDeclaration.Members.Add (method);
  431. if (Style == ServiceDescriptionImportStyle.Client) {
  432. CodeTypeDeclaration.Members.Add (methodBegin);
  433. CodeTypeDeclaration.Members.Add (methodEnd);
  434. }
  435. return method;
  436. }
  437. CodeParameterDeclarationExpression GenerateParameter (XmlMemberMapping member, FieldDirection dir)
  438. {
  439. CodeParameterDeclarationExpression par = new CodeParameterDeclarationExpression (member.TypeFullName, member.MemberName);
  440. par.Direction = dir;
  441. return par;
  442. }
  443. void GenerateMemberAttributes (XmlMembersMapping members, XmlMemberMapping member, SoapBindingUse use, CodeParameterDeclarationExpression param)
  444. {
  445. if (use == SoapBindingUse.Literal)
  446. xmlExporter.AddMappingMetadata (param.CustomAttributes, member, members.Namespace);
  447. else
  448. soapExporter.AddMappingMetadata (param.CustomAttributes, member);
  449. }
  450. void GenerateReturnAttributes (XmlMembersMapping members, XmlMemberMapping member, SoapBindingUse use, CodeMemberMethod method)
  451. {
  452. if (use == SoapBindingUse.Literal)
  453. xmlExporter.AddMappingMetadata (method.ReturnTypeCustomAttributes, member, members.Namespace, (member.ElementName != method.Name + "Result"));
  454. else
  455. soapExporter.AddMappingMetadata (method.ReturnTypeCustomAttributes, member, (member.ElementName != method.Name + "Result"));
  456. }
  457. void ImportHeaders (CodeMemberMethod method)
  458. {
  459. foreach (object ob in OperationBinding.Input.Extensions)
  460. {
  461. SoapHeaderBinding hb = ob as SoapHeaderBinding;
  462. if (hb == null) continue;
  463. if (HasHeader (OperationBinding.Output, hb))
  464. ImportHeader (method, hb, SoapHeaderDirection.In | SoapHeaderDirection.Out);
  465. else
  466. ImportHeader (method, hb, SoapHeaderDirection.In);
  467. }
  468. if (OperationBinding.Output == null) return;
  469. foreach (object ob in OperationBinding.Output.Extensions)
  470. {
  471. SoapHeaderBinding hb = ob as SoapHeaderBinding;
  472. if (hb == null) continue;
  473. if (!HasHeader (OperationBinding.Input, hb))
  474. ImportHeader (method, hb, SoapHeaderDirection.Out);
  475. }
  476. }
  477. bool HasHeader (MessageBinding msg, SoapHeaderBinding hb)
  478. {
  479. if (msg == null) return false;
  480. foreach (object ob in msg.Extensions)
  481. {
  482. SoapHeaderBinding mhb = ob as SoapHeaderBinding;
  483. if ((mhb != null) && (mhb.Message == hb.Message) && (mhb.Part == hb.Part))
  484. return true;
  485. }
  486. return false;
  487. }
  488. void ImportHeader (CodeMemberMethod method, SoapHeaderBinding hb, SoapHeaderDirection direction)
  489. {
  490. Message msg = ServiceDescriptions.GetMessage (hb.Message);
  491. if (msg == null) throw new InvalidOperationException ("Message " + hb.Message + " not found");
  492. MessagePart part = msg.Parts [hb.Part];
  493. if (part == null) throw new InvalidOperationException ("Message part " + hb.Part + " not found in message " + hb.Message);
  494. XmlTypeMapping map;
  495. if (hb.Use == SoapBindingUse.Literal)
  496. {
  497. map = xmlImporter.ImportDerivedTypeMapping (part.Element, typeof (SoapHeader));
  498. xmlExporter.ExportTypeMapping (map);
  499. }
  500. else
  501. {
  502. map = soapImporter.ImportDerivedTypeMapping (part.Type, typeof (SoapHeader), true);
  503. soapExporter.ExportTypeMapping (map);
  504. }
  505. bool required = false;
  506. string varName = headerVariables [map] as string;
  507. if (varName == null)
  508. {
  509. varName = memberIds.AddUnique(CodeIdentifier.MakeValid (map.TypeName + "Value"),hb);
  510. headerVariables.Add (map, varName);
  511. CodeMemberField codeField = new CodeMemberField (map.TypeFullName, varName);
  512. codeField.Attributes = MemberAttributes.Public;
  513. CodeTypeDeclaration.Members.Add (codeField);
  514. }
  515. CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Web.Services.Protocols.SoapHeaderAttribute");
  516. att.Arguments.Add (GetArg (varName));
  517. att.Arguments.Add (GetArg ("Required", required));
  518. if (direction != SoapHeaderDirection.In) att.Arguments.Add (GetEnumArg ("Direction", "System.Web.Services.Protocols.SoapHeaderDirection", direction.ToString ()));
  519. AddCustomAttribute (method, att, true);
  520. }
  521. #endregion
  522. }
  523. }