SoapProtocolImporter.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  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. using System.CodeDom;
  11. using System.Web.Services;
  12. using System.Web.Services.Protocols;
  13. using System.Web.Services.Configuration;
  14. using System.Xml;
  15. using System.Xml.Serialization;
  16. using System.Configuration;
  17. using System.Collections;
  18. namespace System.Web.Services.Description {
  19. public class SoapProtocolImporter : ProtocolImporter {
  20. #region Fields
  21. SoapBinding soapBinding;
  22. SoapCodeExporter soapExporter;
  23. SoapSchemaImporter soapImporter;
  24. XmlCodeExporter xmlExporter;
  25. XmlSchemaImporter xmlImporter;
  26. CodeIdentifiers memberIds;
  27. ArrayList extensionImporters;
  28. Hashtable headerVariables;
  29. #endregion // Fields
  30. #region Constructors
  31. public SoapProtocolImporter ()
  32. {
  33. extensionImporters = ExtensionManager.BuildExtensionImporters ();
  34. }
  35. void SetBinding (SoapBinding soapBinding)
  36. {
  37. this.soapBinding = soapBinding;
  38. }
  39. #endregion // Constructors
  40. #region Properties
  41. public override string ProtocolName {
  42. get { return "Soap"; }
  43. }
  44. public SoapBinding SoapBinding {
  45. get { return soapBinding; }
  46. }
  47. public SoapCodeExporter SoapExporter {
  48. get { return soapExporter; }
  49. }
  50. public SoapSchemaImporter SoapImporter {
  51. get { return soapImporter; }
  52. }
  53. public XmlCodeExporter XmlExporter {
  54. get { return xmlExporter; }
  55. }
  56. public XmlSchemaImporter XmlImporter {
  57. get { return xmlImporter; }
  58. }
  59. #endregion // Properties
  60. #region Methods
  61. protected override CodeTypeDeclaration BeginClass ()
  62. {
  63. soapBinding = (SoapBinding) Binding.Extensions.Find (typeof(SoapBinding));
  64. CodeTypeDeclaration codeClass = new CodeTypeDeclaration (ClassName);
  65. string location = null;
  66. SoapAddressBinding sab = (SoapAddressBinding) Port.Extensions.Find (typeof(SoapAddressBinding));
  67. if (sab != null) location = sab.Location;
  68. string url = GetServiceUrl (location);
  69. CodeTypeReference ctr = new CodeTypeReference ("System.Web.Services.Protocols.SoapHttpClientProtocol");
  70. codeClass.BaseTypes.Add (ctr);
  71. CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Web.Services.WebServiceBinding");
  72. att.Arguments.Add (GetArg ("Name", Port.Name));
  73. att.Arguments.Add (GetArg ("Namespace", Port.Binding.Namespace));
  74. AddCustomAttribute (codeClass, att, true);
  75. CodeConstructor cc = new CodeConstructor ();
  76. cc.Attributes = MemberAttributes.Public;
  77. CodeExpression ce = new CodeFieldReferenceExpression (new CodeThisReferenceExpression(), "Url");
  78. CodeAssignStatement cas = new CodeAssignStatement (ce, new CodePrimitiveExpression (url));
  79. cc.Statements.Add (cas);
  80. codeClass.Members.Add (cc);
  81. memberIds = new CodeIdentifiers ();
  82. headerVariables = new Hashtable ();
  83. return codeClass;
  84. }
  85. protected override void BeginNamespace ()
  86. {
  87. xmlImporter = new XmlSchemaImporter (Schemas, ClassNames);
  88. soapImporter = new SoapSchemaImporter (Schemas, ClassNames);
  89. xmlExporter = new XmlCodeExporter (CodeNamespace, null);
  90. soapExporter = new SoapCodeExporter (CodeNamespace, null);
  91. }
  92. protected override void EndClass ()
  93. {
  94. SoapTransportImporter transportImporter = SoapTransportImporter.FindTransportImporter (soapBinding.Transport);
  95. if (transportImporter == null) throw new InvalidOperationException ("Transport '" + soapBinding.Transport + "' not supported");
  96. transportImporter.ImportContext = this;
  97. transportImporter.ImportClass ();
  98. }
  99. protected override void EndNamespace ()
  100. {
  101. }
  102. protected override bool IsBindingSupported ()
  103. {
  104. return Binding.Extensions.Find (typeof(SoapBinding)) != null;
  105. }
  106. [MonoTODO]
  107. protected override bool IsOperationFlowSupported (OperationFlow flow)
  108. {
  109. throw new NotImplementedException ();
  110. }
  111. protected override CodeMemberMethod GenerateMethod ()
  112. {
  113. try
  114. {
  115. SoapOperationBinding soapOper = OperationBinding.Extensions.Find (typeof (SoapOperationBinding)) as SoapOperationBinding;
  116. if (soapOper == null) throw new InvalidOperationException ("Soap operation binding not found");
  117. SoapBindingStyle style = soapOper.Style != SoapBindingStyle.Default ? soapOper.Style : soapBinding.Style;
  118. SoapBodyBinding isbb = null;
  119. XmlMembersMapping inputMembers = null;
  120. isbb = OperationBinding.Input.Extensions.Find (typeof(SoapBodyBinding)) as SoapBodyBinding;
  121. if (isbb == null) throw new InvalidOperationException ("Soap body binding not found");
  122. inputMembers = ImportMembersMapping (InputMessage, isbb, style, false);
  123. if (inputMembers == null) throw new InvalidOperationException ("Input message not declared");
  124. // If OperationBinding.Output is null, it is an OneWay operation
  125. SoapBodyBinding osbb = null;
  126. XmlMembersMapping outputMembers = null;
  127. if (OperationBinding.Output != null) {
  128. osbb = OperationBinding.Output.Extensions.Find (typeof(SoapBodyBinding)) as SoapBodyBinding;
  129. if (osbb == null) throw new InvalidOperationException ("Soap body binding not found");
  130. outputMembers = ImportMembersMapping (OutputMessage, osbb, style, true);
  131. if (outputMembers == null) throw new InvalidOperationException ("Output message not declared");
  132. }
  133. CodeMemberMethod met = GenerateMethod (memberIds, soapOper, isbb, inputMembers, outputMembers);
  134. if (isbb.Use == SoapBindingUse.Literal)
  135. xmlExporter.ExportMembersMapping (inputMembers);
  136. else
  137. soapExporter.ExportMembersMapping (inputMembers);
  138. if (osbb != null) {
  139. if (osbb.Use == SoapBindingUse.Literal)
  140. xmlExporter.ExportMembersMapping (outputMembers);
  141. else
  142. soapExporter.ExportMembersMapping (outputMembers);
  143. }
  144. foreach (SoapExtensionImporter eximporter in extensionImporters)
  145. {
  146. eximporter.ImportContext = this;
  147. eximporter.ImportMethod (met.CustomAttributes);
  148. }
  149. return met;
  150. }
  151. catch (InvalidOperationException ex)
  152. {
  153. UnsupportedOperationBindingWarning (ex.Message);
  154. return null;
  155. }
  156. }
  157. XmlMembersMapping ImportMembersMapping (Message msg, SoapBodyBinding sbb, SoapBindingStyle style, bool output)
  158. {
  159. XmlQualifiedName elem = null;
  160. string elemName = Operation.Name;
  161. if (output) elemName += "Response";
  162. if (msg.Parts.Count == 1 && msg.Parts[0].Name == "parameters")
  163. {
  164. // Wrapped parameter style
  165. MessagePart part = msg.Parts[0];
  166. if (sbb.Use == SoapBindingUse.Encoded)
  167. {
  168. SoapSchemaMember ssm = new SoapSchemaMember ();
  169. ssm.MemberName = part.Name;
  170. ssm.MemberType = part.Type;
  171. return soapImporter.ImportMembersMapping (elemName, part.Type.Namespace, ssm);
  172. }
  173. else
  174. return xmlImporter.ImportMembersMapping (part.Element);
  175. }
  176. else
  177. {
  178. if (sbb.Use == SoapBindingUse.Encoded)
  179. {
  180. SoapSchemaMember[] mems = new SoapSchemaMember [msg.Parts.Count];
  181. for (int n=0; n<mems.Length; n++)
  182. {
  183. SoapSchemaMember mem = new SoapSchemaMember();
  184. mem.MemberName = msg.Parts[n].Name;
  185. mem.MemberType = msg.Parts[n].Type;
  186. mems[n] = mem;
  187. }
  188. // Rpc messages always have a wrapping element
  189. if (style == SoapBindingStyle.Rpc)
  190. return soapImporter.ImportMembersMapping (elemName, sbb.Namespace, mems, true);
  191. else
  192. return soapImporter.ImportMembersMapping ("", "", mems, false);
  193. }
  194. else
  195. {
  196. if (style == SoapBindingStyle.Rpc)
  197. throw new InvalidOperationException ("The combination of style=rpc with use=literal is not supported");
  198. XmlQualifiedName[] pnames = new XmlQualifiedName [msg.Parts.Count];
  199. for (int n=0; n<pnames.Length; n++)
  200. pnames[n] = msg.Parts[n].Element;
  201. return xmlImporter.ImportMembersMapping (pnames);
  202. }
  203. }
  204. }
  205. CodeMemberMethod GenerateMethod (CodeIdentifiers memberIds, SoapOperationBinding soapOper, SoapBodyBinding bodyBinding, XmlMembersMapping inputMembers, XmlMembersMapping outputMembers)
  206. {
  207. CodeIdentifiers pids = new CodeIdentifiers ();
  208. CodeMemberMethod method = new CodeMemberMethod ();
  209. CodeMemberMethod methodBegin = new CodeMemberMethod ();
  210. CodeMemberMethod methodEnd = new CodeMemberMethod ();
  211. method.Attributes = MemberAttributes.Public;
  212. methodBegin.Attributes = MemberAttributes.Public;
  213. methodEnd.Attributes = MemberAttributes.Public;
  214. SoapBindingStyle style = soapOper.Style != SoapBindingStyle.Default ? soapOper.Style : soapBinding.Style;
  215. // Find unique names for temporary variables
  216. for (int n=0; n<inputMembers.Count; n++)
  217. pids.AddUnique (inputMembers[n].MemberName, inputMembers[n]);
  218. if (outputMembers != null)
  219. for (int n=0; n<outputMembers.Count; n++)
  220. pids.AddUnique (outputMembers[n].MemberName, outputMembers[n]);
  221. string varAsyncResult = pids.AddUnique ("asyncResult","asyncResult");
  222. string varResults = pids.AddUnique ("results","results");
  223. string varCallback = pids.AddUnique ("callback","callback");
  224. string varAsyncState = pids.AddUnique ("asyncState","asyncState");
  225. string messageName = memberIds.AddUnique(CodeIdentifier.MakeValid(Operation.Name),method);
  226. method.Name = CodeIdentifier.MakeValid(Operation.Name);
  227. if (method.Name == ClassName) method.Name += "1";
  228. methodBegin.Name = memberIds.AddUnique(CodeIdentifier.MakeValid("Begin" + memberIds.MakeRightCase(method.Name)),method);
  229. methodEnd.Name = memberIds.AddUnique(CodeIdentifier.MakeValid("End" + memberIds.MakeRightCase(method.Name)),method);
  230. method.ReturnType = new CodeTypeReference (typeof(void));
  231. methodEnd.ReturnType = new CodeTypeReference (typeof(void));
  232. methodEnd.Parameters.Add (new CodeParameterDeclarationExpression (typeof (IAsyncResult),varAsyncResult));
  233. CodeExpression[] paramArray = new CodeExpression [inputMembers.Count];
  234. CodeParameterDeclarationExpression[] outParams = new CodeParameterDeclarationExpression [outputMembers != null ? outputMembers.Count : 0];
  235. for (int n=0; n<inputMembers.Count; n++)
  236. {
  237. CodeParameterDeclarationExpression param = GenerateParameter (inputMembers[n], FieldDirection.In);
  238. method.Parameters.Add (param);
  239. GenerateMemberAttributes (inputMembers, inputMembers[n], bodyBinding.Use, param);
  240. methodBegin.Parameters.Add (GenerateParameter (inputMembers[n], FieldDirection.In));
  241. paramArray [n] = new CodeVariableReferenceExpression (param.Name);
  242. }
  243. if (outputMembers != null)
  244. {
  245. for (int n=0; n<outputMembers.Count; n++)
  246. {
  247. CodeParameterDeclarationExpression cpd = GenerateParameter (outputMembers[n], FieldDirection.Out);
  248. outParams [n] = cpd;
  249. bool found = false;
  250. foreach (CodeParameterDeclarationExpression ip in method.Parameters)
  251. {
  252. if (ip.Name == cpd.Name && ip.Type.BaseType == cpd.Type.BaseType) {
  253. ip.Direction = FieldDirection.Ref;
  254. methodEnd.Parameters.Add (GenerateParameter (outputMembers[n], FieldDirection.Out));
  255. found = true;
  256. break;
  257. }
  258. }
  259. if (found) continue;
  260. if ((outputMembers [n].ElementName == Operation.Name + "Result") ||
  261. (outputMembers.Count==1))
  262. {
  263. method.ReturnType = cpd.Type;
  264. methodEnd.ReturnType = cpd.Type;
  265. GenerateReturnAttributes (outputMembers, outputMembers[n], bodyBinding.Use, method);
  266. outParams [n] = null;
  267. continue;
  268. }
  269. method.Parameters.Add (cpd);
  270. GenerateMemberAttributes (outputMembers, outputMembers[n], bodyBinding.Use, cpd);
  271. methodEnd.Parameters.Add (GenerateParameter (outputMembers[n], FieldDirection.Out));
  272. }
  273. }
  274. methodBegin.Parameters.Add (new CodeParameterDeclarationExpression (typeof (AsyncCallback),varCallback));
  275. methodBegin.Parameters.Add (new CodeParameterDeclarationExpression (typeof (object),varAsyncState));
  276. methodBegin.ReturnType = new CodeTypeReference (typeof(IAsyncResult));
  277. // Array of input parameters
  278. CodeArrayCreateExpression methodParams;
  279. if (paramArray.Length > 0)
  280. methodParams = new CodeArrayCreateExpression (typeof(object), paramArray);
  281. else
  282. methodParams = new CodeArrayCreateExpression (typeof(object), 0);
  283. // Assignment of output parameters
  284. CodeStatementCollection outAssign = new CodeStatementCollection ();
  285. CodeVariableReferenceExpression arrVar = new CodeVariableReferenceExpression (varResults);
  286. for (int n=0; n<outParams.Length; n++)
  287. {
  288. CodeExpression index = new CodePrimitiveExpression (n);
  289. if (outParams[n] == null)
  290. {
  291. CodeExpression res = new CodeCastExpression (method.ReturnType, new CodeArrayIndexerExpression (arrVar, index));
  292. outAssign.Add (new CodeMethodReturnStatement (res));
  293. }
  294. else
  295. {
  296. CodeExpression res = new CodeCastExpression (outParams[n].Type, new CodeArrayIndexerExpression (arrVar, index));
  297. CodeExpression var = new CodeVariableReferenceExpression (outParams[n].Name);
  298. outAssign.Insert (0, new CodeAssignStatement (var, res));
  299. }
  300. }
  301. // Invoke call
  302. CodeThisReferenceExpression ethis = new CodeThisReferenceExpression();
  303. CodePrimitiveExpression varMsgName = new CodePrimitiveExpression (messageName);
  304. CodeMethodInvokeExpression inv;
  305. CodeVariableDeclarationStatement dec;
  306. inv = new CodeMethodInvokeExpression (ethis, "Invoke", varMsgName, methodParams);
  307. if (outputMembers != null && outputMembers.Count > 0)
  308. {
  309. dec = new CodeVariableDeclarationStatement (typeof(object[]), varResults, inv);
  310. method.Statements.Add (dec);
  311. method.Statements.AddRange (outAssign);
  312. }
  313. else
  314. method.Statements.Add (inv);
  315. // Begin Invoke Call
  316. CodeExpression expCallb = new CodeVariableReferenceExpression (varCallback);
  317. CodeExpression expAsyncs = new CodeVariableReferenceExpression (varAsyncState);
  318. inv = new CodeMethodInvokeExpression (ethis, "BeginInvoke", varMsgName, methodParams, expCallb, expAsyncs);
  319. methodBegin.Statements.Add (new CodeMethodReturnStatement (inv));
  320. // End Invoke call
  321. CodeExpression varAsyncr = new CodeVariableReferenceExpression (varAsyncResult);
  322. inv = new CodeMethodInvokeExpression (ethis, "EndInvoke", varAsyncr);
  323. if (outputMembers != null && outputMembers.Count > 0)
  324. {
  325. dec = new CodeVariableDeclarationStatement (typeof(object[]), varResults, inv);
  326. methodEnd.Statements.Add (dec);
  327. methodEnd.Statements.AddRange (outAssign);
  328. }
  329. else
  330. methodEnd.Statements.Add (inv);
  331. // Attributes
  332. ImportHeaders (method);
  333. CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Web.Services.WebMethodAttribute");
  334. if (messageName != method.Name) att.Arguments.Add (GetArg ("MessageName",messageName));
  335. AddCustomAttribute (method, att, false);
  336. if (style == SoapBindingStyle.Rpc)
  337. {
  338. att = new CodeAttributeDeclaration ("System.Web.Services.Protocols.SoapRpcMethodAttribute");
  339. att.Arguments.Add (GetArg (soapOper.SoapAction));
  340. if (inputMembers.ElementName != method.Name) att.Arguments.Add (GetArg ("RequestElementName", inputMembers.ElementName));
  341. if (outputMembers != null && outputMembers.ElementName != (method.Name + "Response")) att.Arguments.Add (GetArg ("ResponseElementName", outputMembers.ElementName));
  342. att.Arguments.Add (GetArg ("RequestNamespace", inputMembers.Namespace));
  343. if (outputMembers != null) att.Arguments.Add (GetArg ("ResponseNamespace", outputMembers.Namespace));
  344. if (outputMembers == null) att.Arguments.Add (GetArg ("OneWay", true));
  345. }
  346. else
  347. {
  348. if (outputMembers != null && (inputMembers.ElementName == "" && outputMembers.ElementName != "" ||
  349. inputMembers.ElementName != "" && outputMembers.ElementName == ""))
  350. throw new InvalidOperationException ("Parameter style is not the same for the input message and output message");
  351. att = new CodeAttributeDeclaration ("System.Web.Services.Protocols.SoapDocumentMethodAttribute");
  352. att.Arguments.Add (GetArg (soapOper.SoapAction));
  353. if (inputMembers.ElementName != "") {
  354. if (inputMembers.ElementName != method.Name) att.Arguments.Add (GetArg ("RequestElementName", inputMembers.ElementName));
  355. if (outputMembers != null && outputMembers.ElementName != (method.Name + "Response")) att.Arguments.Add (GetArg ("ResponseElementName", outputMembers.ElementName));
  356. att.Arguments.Add (GetArg ("RequestNamespace", inputMembers.Namespace));
  357. if (outputMembers != null) att.Arguments.Add (GetArg ("ResponseNamespace", outputMembers.Namespace));
  358. att.Arguments.Add (GetEnumArg ("ParameterStyle", "System.Web.Services.Protocols.SoapParameterStyle", "Wrapped"));
  359. }
  360. else
  361. att.Arguments.Add (GetEnumArg ("ParameterStyle", "System.Web.Services.Protocols.SoapParameterStyle", "Bare"));
  362. if (outputMembers == null) att.Arguments.Add (GetArg ("OneWay", true));
  363. att.Arguments.Add (GetEnumArg ("Use", "System.Web.Services.Description.SoapBindingUse", bodyBinding.Use.ToString()));
  364. }
  365. AddCustomAttribute (method, att, true);
  366. CodeTypeDeclaration.Members.Add (method);
  367. CodeTypeDeclaration.Members.Add (methodBegin);
  368. CodeTypeDeclaration.Members.Add (methodEnd);
  369. return method;
  370. }
  371. CodeParameterDeclarationExpression GenerateParameter (XmlMemberMapping member, FieldDirection dir)
  372. {
  373. CodeParameterDeclarationExpression par = new CodeParameterDeclarationExpression (member.TypeFullName, member.MemberName);
  374. par.Direction = dir;
  375. return par;
  376. }
  377. void GenerateMemberAttributes (XmlMembersMapping members, XmlMemberMapping member, SoapBindingUse use, CodeParameterDeclarationExpression param)
  378. {
  379. if (use == SoapBindingUse.Literal)
  380. xmlExporter.AddMappingMetadata (param.CustomAttributes, member, members.Namespace);
  381. else
  382. soapExporter.AddMappingMetadata (param.CustomAttributes, member);
  383. }
  384. void GenerateReturnAttributes (XmlMembersMapping members, XmlMemberMapping member, SoapBindingUse use, CodeMemberMethod method)
  385. {
  386. if (use == SoapBindingUse.Literal)
  387. xmlExporter.AddMappingMetadata (method.ReturnTypeCustomAttributes, member, members.Namespace, (member.ElementName != method.Name + "Result"));
  388. else
  389. soapExporter.AddMappingMetadata (method.ReturnTypeCustomAttributes, member, (member.ElementName != method.Name + "Result"));
  390. }
  391. void ImportHeaders (CodeMemberMethod method)
  392. {
  393. foreach (object ob in OperationBinding.Input.Extensions)
  394. {
  395. SoapHeaderBinding hb = ob as SoapHeaderBinding;
  396. if (hb == null) continue;
  397. if (HasHeader (OperationBinding.Output, hb))
  398. ImportHeader (method, hb, SoapHeaderDirection.In | SoapHeaderDirection.Out);
  399. else
  400. ImportHeader (method, hb, SoapHeaderDirection.In);
  401. }
  402. if (OperationBinding.Output == null) return;
  403. foreach (object ob in OperationBinding.Output.Extensions)
  404. {
  405. SoapHeaderBinding hb = ob as SoapHeaderBinding;
  406. if (hb == null) continue;
  407. if (!HasHeader (OperationBinding.Input, hb))
  408. ImportHeader (method, hb, SoapHeaderDirection.Out);
  409. }
  410. }
  411. bool HasHeader (MessageBinding msg, SoapHeaderBinding hb)
  412. {
  413. if (msg == null) return false;
  414. foreach (object ob in msg.Extensions)
  415. {
  416. SoapHeaderBinding mhb = ob as SoapHeaderBinding;
  417. if ((mhb != null) && (mhb.Message == hb.Message) && (mhb.Part == hb.Part))
  418. return true;
  419. }
  420. return false;
  421. }
  422. void ImportHeader (CodeMemberMethod method, SoapHeaderBinding hb, SoapHeaderDirection direction)
  423. {
  424. Message msg = ServiceDescriptions.GetMessage (hb.Message);
  425. if (msg == null) throw new InvalidOperationException ("Message " + hb.Message + " not found");
  426. MessagePart part = msg.Parts [hb.Part];
  427. if (part == null) throw new InvalidOperationException ("Message part " + hb.Part + " not found in message " + hb.Message);
  428. XmlTypeMapping map;
  429. if (hb.Use == SoapBindingUse.Literal)
  430. {
  431. map = xmlImporter.ImportDerivedTypeMapping (part.Element, typeof (SoapHeader));
  432. xmlExporter.ExportTypeMapping (map);
  433. }
  434. else
  435. {
  436. map = soapImporter.ImportDerivedTypeMapping (part.Type, typeof (SoapHeader), true);
  437. soapExporter.ExportTypeMapping (map);
  438. }
  439. bool required = false;
  440. string varName = headerVariables [map] as string;
  441. if (varName == null)
  442. {
  443. varName = memberIds.AddUnique(CodeIdentifier.MakeValid (hb.Part + "Value"),hb);
  444. headerVariables.Add (map, varName);
  445. CodeMemberField codeField = new CodeMemberField (map.TypeFullName, varName);
  446. codeField.Attributes = MemberAttributes.Public;
  447. CodeTypeDeclaration.Members.Add (codeField);
  448. }
  449. CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Web.Services.Protocols.SoapHeaderAttribute");
  450. att.Arguments.Add (GetArg (varName));
  451. att.Arguments.Add (GetArg ("Required", required));
  452. if (direction != SoapHeaderDirection.In) att.Arguments.Add (GetEnumArg ("Direction", "System.Web.Services.Protocols.SoapHeaderDirection", direction.ToString ()));
  453. AddCustomAttribute (method, att, true);
  454. }
  455. #endregion
  456. }
  457. }