2 // System.Web.Services.Description.SoapProtocolImporter.cs
5 // Tim Coleman (tim@timcoleman.com)
6 // Lluis Sanchez Gual (lluis@ximian.com)
8 // Copyright (C) Tim Coleman, 2002
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Web.Services;
34 using System.Web.Services.Protocols;
35 using System.Web.Services.Configuration;
37 using System.Xml.Schema;
38 using System.Xml.Serialization;
39 using System.Configuration;
40 using System.Collections;
42 namespace System.Web.Services.Description {
43 public class SoapProtocolImporter : ProtocolImporter {
47 SoapBinding soapBinding;
48 SoapCodeExporter soapExporter;
49 SoapSchemaImporter soapImporter;
50 XmlCodeExporter xmlExporter;
51 XmlSchemaImporter xmlImporter;
52 CodeIdentifiers memberIds;
53 ArrayList extensionImporters;
54 Hashtable headerVariables;
55 XmlSchemas xmlSchemas;
56 XmlSchemas soapSchemas;
62 public SoapProtocolImporter ()
64 extensionImporters = ExtensionManager.BuildExtensionImporters ();
67 void SetBinding (SoapBinding soapBinding)
69 this.soapBinding = soapBinding;
72 #endregion // Constructors
76 public override string ProtocolName {
77 get { return "Soap"; }
80 public SoapBinding SoapBinding {
81 get { return soapBinding; }
84 public SoapCodeExporter SoapExporter {
85 get { return soapExporter; }
88 public SoapSchemaImporter SoapImporter {
89 get { return soapImporter; }
92 public XmlCodeExporter XmlExporter {
93 get { return xmlExporter; }
96 public XmlSchemaImporter XmlImporter {
97 get { return xmlImporter; }
100 #endregion // Properties
104 protected override CodeTypeDeclaration BeginClass ()
106 soapBinding = (SoapBinding) Binding.Extensions.Find (typeof(SoapBinding));
108 CodeTypeDeclaration codeClass = new CodeTypeDeclaration (ClassName);
110 codeClass.IsPartial = true;
113 string location = null;
116 SoapAddressBinding sab = (SoapAddressBinding) Port.Extensions.Find (typeof(SoapAddressBinding));
117 if (sab != null) location = sab.Location;
120 string namspace = (Port != null ? Port.Binding.Namespace : Binding.ServiceDescription.TargetNamespace);
121 string name = (Port != null ? Port.Name : Binding.Name);
123 if (Style == ServiceDescriptionImportStyle.Client) {
124 CodeTypeReference ctr = new CodeTypeReference ("System.Web.Services.Protocols.SoapHttpClientProtocol");
125 codeClass.BaseTypes.Add (ctr);
128 CodeTypeReference ctr = new CodeTypeReference ("System.Web.Services.WebService");
129 codeClass.BaseTypes.Add (ctr);
130 CodeAttributeDeclaration attws = new CodeAttributeDeclaration ("System.Web.Services.WebServiceAttribute");
131 attws.Arguments.Add (GetArg ("Namespace", namspace));
132 AddCustomAttribute (codeClass, attws, true);
135 CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Web.Services.WebServiceBinding");
136 att.Arguments.Add (GetArg ("Name", name));
137 att.Arguments.Add (GetArg ("Namespace", namspace));
138 AddCustomAttribute (codeClass, att, true);
140 if (Style == ServiceDescriptionImportStyle.Client) {
141 CodeConstructor cc = new CodeConstructor ();
142 cc.Attributes = MemberAttributes.Public;
143 GenerateServiceUrl (location, cc.Statements);
146 if (ProtocolName.ToUpper () == "SOAP12") {
147 CodeExpression thisSoapVer = new CodeFieldReferenceExpression (new CodeThisReferenceExpression(), "SoapVersion");
148 CodeFieldReferenceExpression soap12Enum =
149 new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (typeof (SoapProtocolVersion)), "Soap12");
150 cc.Statements.Add (new CodeAssignStatement (thisSoapVer, soap12Enum));
153 codeClass.Members.Add (cc);
156 memberIds = new CodeIdentifiers ();
157 headerVariables = new Hashtable ();
161 protected override void BeginNamespace ()
164 xmlImporter = new XmlSchemaImporter (LiteralSchemas, base.CodeGenerationOptions, base.CodeGenerator, base.ImportContext);
165 soapImporter = new SoapSchemaImporter (EncodedSchemas, base.CodeGenerationOptions, base.CodeGenerator, base.ImportContext);
166 xmlExporter = new XmlCodeExporter (CodeNamespace, null, base.CodeGenerator, base.CodeGenerationOptions, null);
167 soapExporter = new SoapCodeExporter (CodeNamespace, null, base.CodeGenerator, base.CodeGenerationOptions, null);
169 xmlImporter = new XmlSchemaImporter (LiteralSchemas, ClassNames);
170 soapImporter = new SoapSchemaImporter (EncodedSchemas, ClassNames);
171 xmlExporter = new XmlCodeExporter (CodeNamespace, null);
172 soapExporter = new SoapCodeExporter (CodeNamespace, null);
176 protected override void EndClass ()
178 SoapTransportImporter transportImporter = SoapTransportImporter.FindTransportImporter (soapBinding.Transport);
179 if (transportImporter == null) throw new InvalidOperationException ("Transport '" + soapBinding.Transport + "' not supported");
180 transportImporter.ImportContext = this;
181 transportImporter.ImportClass ();
183 if (xmlExporter.IncludeMetadata.Count > 0 || soapExporter.IncludeMetadata.Count > 0)
185 if (CodeTypeDeclaration.CustomAttributes == null)
186 CodeTypeDeclaration.CustomAttributes = new CodeAttributeDeclarationCollection ();
187 CodeTypeDeclaration.CustomAttributes.AddRange (xmlExporter.IncludeMetadata);
188 CodeTypeDeclaration.CustomAttributes.AddRange (soapExporter.IncludeMetadata);
192 protected override void EndNamespace ()
196 protected override bool IsBindingSupported ()
199 object o = Binding.Extensions.Find (typeof(SoapBinding));
200 return o != null && !(o is Soap12Binding);
202 return Binding.Extensions.Find (typeof(SoapBinding)) != null;
207 protected override bool IsOperationFlowSupported (OperationFlow flow)
209 throw new NotImplementedException ();
212 static readonly char [] whitespaces = new char [] {' ', '\t', '\n', '\r'};
214 protected virtual bool IsSoapEncodingPresent (string uriList)
216 foreach (string s in uriList.Split (whitespaces))
217 if (s == "http://schemas.xmlsoap.org/soap/encoding/")
222 protected override CodeMemberMethod GenerateMethod ()
226 SoapOperationBinding soapOper = OperationBinding.Extensions.Find (typeof (SoapOperationBinding)) as SoapOperationBinding;
227 if (soapOper == null) throw new InvalidOperationException ("Soap operation binding not found");
229 SoapBindingStyle style = soapOper.Style != SoapBindingStyle.Default ? soapOper.Style : soapBinding.Style;
231 SoapBodyBinding isbb = null;
232 XmlMembersMapping inputMembers = null;
234 bool isWrapped = CheckIsWrapped ();
236 isbb = OperationBinding.Input.Extensions.Find (typeof(SoapBodyBinding)) as SoapBodyBinding;
237 if (isbb == null) throw new InvalidOperationException ("Soap body binding not found");
239 inputMembers = ImportMembersMapping (InputMessage, isbb, style, false, isWrapped);
240 if (inputMembers == null) throw new InvalidOperationException ("Input message not declared");
242 // If OperationBinding.Output is null, it is an OneWay operation
244 SoapBodyBinding osbb = null;
245 XmlMembersMapping outputMembers = null;
247 if (OperationBinding.Output != null) {
248 osbb = OperationBinding.Output.Extensions.Find (typeof(SoapBodyBinding)) as SoapBodyBinding;
249 if (osbb == null) throw new InvalidOperationException ("Soap body binding not found");
251 outputMembers = ImportMembersMapping (OutputMessage, osbb, style, true, isWrapped);
252 if (outputMembers == null) throw new InvalidOperationException ("Output message not declared");
255 CodeMemberMethod met = GenerateMethod (memberIds, soapOper, isbb, inputMembers, outputMembers);
257 if (isbb.Use == SoapBindingUse.Literal)
258 xmlExporter.ExportMembersMapping (inputMembers);
260 soapExporter.ExportMembersMapping (inputMembers);
263 if (osbb.Use == SoapBindingUse.Literal)
264 xmlExporter.ExportMembersMapping (outputMembers);
266 soapExporter.ExportMembersMapping (outputMembers);
269 foreach (SoapExtensionImporter eximporter in extensionImporters)
271 eximporter.ImportContext = this;
272 eximporter.ImportMethod (met.CustomAttributes);
277 catch (InvalidOperationException ex)
279 UnsupportedOperationBindingWarning (ex.Message);
284 bool CheckIsWrapped ()
286 return (OutputMessage == null || (OutputMessage.Parts.Count == 1 && OutputMessage.Parts[0].Name == "parameters")) &&
287 (InputMessage == null || (InputMessage.Parts.Count == 1 && InputMessage.Parts[0].Name == "parameters"));
290 XmlMembersMapping ImportMembersMapping (Message msg, SoapBodyBinding sbb, SoapBindingStyle style, bool output, bool wrapped)
292 string elemName = Operation.Name;
293 if (output) elemName += "Response";
297 // Wrapped parameter style
299 MessagePart part = msg.Parts[0];
300 if (sbb.Use == SoapBindingUse.Encoded)
302 SoapSchemaMember ssm = new SoapSchemaMember ();
303 ssm.MemberName = part.Name;
304 ssm.MemberType = part.Type;
305 return soapImporter.ImportMembersMapping (elemName, part.Type.Namespace, ssm);
308 return xmlImporter.ImportMembersMapping (part.Element);
312 if (sbb.Use == SoapBindingUse.Encoded)
314 SoapSchemaMember[] mems = new SoapSchemaMember [msg.Parts.Count];
315 for (int n=0; n<mems.Length; n++)
317 SoapSchemaMember mem = new SoapSchemaMember();
318 mem.MemberName = msg.Parts[n].Name;
319 mem.MemberType = msg.Parts[n].Type;
323 // Rpc messages always have a wrapping element
324 if (style == SoapBindingStyle.Rpc)
325 return soapImporter.ImportMembersMapping (elemName, sbb.Namespace, mems, true);
327 return soapImporter.ImportMembersMapping ("", "", mems, false);
331 if (style == SoapBindingStyle.Rpc)
332 throw new InvalidOperationException ("The combination of style=rpc with use=literal is not supported");
334 if (msg.Parts.Count == 1 && msg.Parts[0].Type != XmlQualifiedName.Empty)
335 return xmlImporter.ImportAnyType (msg.Parts[0].Type, null);
338 XmlQualifiedName[] pnames = new XmlQualifiedName [msg.Parts.Count];
339 for (int n=0; n<pnames.Length; n++)
340 pnames[n] = msg.Parts[n].Element;
341 return xmlImporter.ImportMembersMapping (pnames);
347 CodeMemberMethod GenerateMethod (CodeIdentifiers memberIds, SoapOperationBinding soapOper, SoapBodyBinding bodyBinding, XmlMembersMapping inputMembers, XmlMembersMapping outputMembers)
349 CodeIdentifiers pids = new CodeIdentifiers ();
350 CodeMemberMethod method = new CodeMemberMethod ();
351 CodeMemberMethod methodBegin = new CodeMemberMethod ();
352 CodeMemberMethod methodEnd = new CodeMemberMethod ();
353 method.Attributes = MemberAttributes.Public | MemberAttributes.Final;
354 methodBegin.Attributes = MemberAttributes.Public | MemberAttributes.Final;
355 methodEnd.Attributes = MemberAttributes.Public | MemberAttributes.Final;
357 SoapBindingStyle style = soapOper.Style != SoapBindingStyle.Default ? soapOper.Style : soapBinding.Style;
359 // Find unique names for temporary variables
361 for (int n=0; n<inputMembers.Count; n++)
362 pids.AddUnique (inputMembers[n].MemberName, inputMembers[n]);
364 if (outputMembers != null)
365 for (int n=0; n<outputMembers.Count; n++)
366 pids.AddUnique (outputMembers[n].MemberName, outputMembers[n]);
368 string varAsyncResult = pids.AddUnique ("asyncResult","asyncResult");
369 string varResults = pids.AddUnique ("results","results");
370 string varCallback = pids.AddUnique ("callback","callback");
371 string varAsyncState = pids.AddUnique ("asyncState","asyncState");
373 string messageName = memberIds.AddUnique(CodeIdentifier.MakeValid(Operation.Name),method);
375 method.Name = CodeIdentifier.MakeValid(Operation.Name);
376 if (method.Name == ClassName) method.Name += "1";
377 methodBegin.Name = memberIds.AddUnique(CodeIdentifier.MakeValid("Begin" + method.Name),method);
378 methodEnd.Name = memberIds.AddUnique(CodeIdentifier.MakeValid("End" + method.Name),method);
380 method.ReturnType = new CodeTypeReference (typeof(void));
381 methodEnd.ReturnType = new CodeTypeReference (typeof(void));
382 methodEnd.Parameters.Add (new CodeParameterDeclarationExpression (typeof (IAsyncResult),varAsyncResult));
384 CodeExpression[] paramArray = new CodeExpression [inputMembers.Count];
385 CodeParameterDeclarationExpression[] outParams = new CodeParameterDeclarationExpression [outputMembers != null ? outputMembers.Count : 0];
387 for (int n=0; n<inputMembers.Count; n++)
389 CodeParameterDeclarationExpression param = GenerateParameter (inputMembers[n], FieldDirection.In);
390 method.Parameters.Add (param);
391 GenerateMemberAttributes (inputMembers, inputMembers[n], bodyBinding.Use, param);
392 methodBegin.Parameters.Add (GenerateParameter (inputMembers[n], FieldDirection.In));
393 paramArray [n] = new CodeVariableReferenceExpression (param.Name);
396 if (outputMembers != null)
398 bool hasReturn = false;
399 for (int n=0; n<outputMembers.Count; n++)
401 CodeParameterDeclarationExpression cpd = GenerateParameter (outputMembers[n], FieldDirection.Out);
405 foreach (CodeParameterDeclarationExpression ip in method.Parameters)
407 if (ip.Name == cpd.Name && ip.Type.BaseType == cpd.Type.BaseType) {
408 ip.Direction = FieldDirection.Ref;
409 methodEnd.Parameters.Add (GenerateParameter (outputMembers[n], FieldDirection.Out));
420 method.ReturnType = cpd.Type;
421 methodEnd.ReturnType = cpd.Type;
422 GenerateReturnAttributes (outputMembers, outputMembers[n], bodyBinding.Use, method);
423 outParams [n] = null;
427 method.Parameters.Add (cpd);
428 GenerateMemberAttributes (outputMembers, outputMembers[n], bodyBinding.Use, cpd);
429 methodEnd.Parameters.Add (GenerateParameter (outputMembers[n], FieldDirection.Out));
433 methodBegin.Parameters.Add (new CodeParameterDeclarationExpression (typeof (AsyncCallback),varCallback));
434 methodBegin.Parameters.Add (new CodeParameterDeclarationExpression (typeof (object),varAsyncState));
435 methodBegin.ReturnType = new CodeTypeReference (typeof(IAsyncResult));
437 // Array of input parameters
439 CodeArrayCreateExpression methodParams;
440 if (paramArray.Length > 0)
441 methodParams = new CodeArrayCreateExpression (typeof(object), paramArray);
443 methodParams = new CodeArrayCreateExpression (typeof(object), 0);
445 // Assignment of output parameters
447 CodeStatementCollection outAssign = new CodeStatementCollection ();
448 CodeVariableReferenceExpression arrVar = new CodeVariableReferenceExpression (varResults);
449 for (int n=0; n<outParams.Length; n++)
451 CodeExpression index = new CodePrimitiveExpression (n);
452 if (outParams[n] == null)
454 CodeExpression res = new CodeCastExpression (method.ReturnType, new CodeArrayIndexerExpression (arrVar, index));
455 outAssign.Add (new CodeMethodReturnStatement (res));
459 CodeExpression res = new CodeCastExpression (outParams[n].Type, new CodeArrayIndexerExpression (arrVar, index));
460 CodeExpression var = new CodeVariableReferenceExpression (outParams[n].Name);
461 outAssign.Insert (0, new CodeAssignStatement (var, res));
465 if (Style == ServiceDescriptionImportStyle.Client)
469 CodeThisReferenceExpression ethis = new CodeThisReferenceExpression();
470 CodePrimitiveExpression varMsgName = new CodePrimitiveExpression (messageName);
471 CodeMethodInvokeExpression inv;
472 CodeVariableDeclarationStatement dec;
474 inv = new CodeMethodInvokeExpression (ethis, "Invoke", varMsgName, methodParams);
475 if (outputMembers != null && outputMembers.Count > 0)
477 dec = new CodeVariableDeclarationStatement (typeof(object[]), varResults, inv);
478 method.Statements.Add (dec);
479 method.Statements.AddRange (outAssign);
482 method.Statements.Add (inv);
486 CodeExpression expCallb = new CodeVariableReferenceExpression (varCallback);
487 CodeExpression expAsyncs = new CodeVariableReferenceExpression (varAsyncState);
488 inv = new CodeMethodInvokeExpression (ethis, "BeginInvoke", varMsgName, methodParams, expCallb, expAsyncs);
489 methodBegin.Statements.Add (new CodeMethodReturnStatement (inv));
493 CodeExpression varAsyncr = new CodeVariableReferenceExpression (varAsyncResult);
494 inv = new CodeMethodInvokeExpression (ethis, "EndInvoke", varAsyncr);
495 if (outputMembers != null && outputMembers.Count > 0)
497 dec = new CodeVariableDeclarationStatement (typeof(object[]), varResults, inv);
498 methodEnd.Statements.Add (dec);
499 methodEnd.Statements.AddRange (outAssign);
502 methodEnd.Statements.Add (inv);
505 method.Attributes = MemberAttributes.Public | MemberAttributes.Abstract;
510 ImportHeaders (method);
512 CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Web.Services.WebMethodAttribute");
513 if (messageName != method.Name) att.Arguments.Add (GetArg ("MessageName",messageName));
514 AddCustomAttribute (method, att, (Style == ServiceDescriptionImportStyle.Server));
516 if (style == SoapBindingStyle.Rpc)
518 att = new CodeAttributeDeclaration ("System.Web.Services.Protocols.SoapRpcMethodAttribute");
519 att.Arguments.Add (GetArg (soapOper.SoapAction));
520 if (inputMembers.ElementName != method.Name) att.Arguments.Add (GetArg ("RequestElementName", inputMembers.ElementName));
521 if (outputMembers != null && outputMembers.ElementName != (method.Name + "Response")) att.Arguments.Add (GetArg ("ResponseElementName", outputMembers.ElementName));
522 att.Arguments.Add (GetArg ("RequestNamespace", inputMembers.Namespace));
523 if (outputMembers != null) att.Arguments.Add (GetArg ("ResponseNamespace", outputMembers.Namespace));
524 if (outputMembers == null) att.Arguments.Add (GetArg ("OneWay", true));
528 if (outputMembers != null && (inputMembers.ElementName == "" && outputMembers.ElementName != "" ||
529 inputMembers.ElementName != "" && outputMembers.ElementName == ""))
530 throw new InvalidOperationException ("Parameter style is not the same for the input message and output message");
532 att = new CodeAttributeDeclaration ("System.Web.Services.Protocols.SoapDocumentMethodAttribute");
533 att.Arguments.Add (GetArg (soapOper.SoapAction));
534 if (inputMembers.ElementName != "") {
535 if (inputMembers.ElementName != method.Name) att.Arguments.Add (GetArg ("RequestElementName", inputMembers.ElementName));
536 if (outputMembers != null && outputMembers.ElementName != (method.Name + "Response")) att.Arguments.Add (GetArg ("ResponseElementName", outputMembers.ElementName));
537 att.Arguments.Add (GetArg ("RequestNamespace", inputMembers.Namespace));
538 if (outputMembers != null) att.Arguments.Add (GetArg ("ResponseNamespace", outputMembers.Namespace));
539 att.Arguments.Add (GetEnumArg ("ParameterStyle", "System.Web.Services.Protocols.SoapParameterStyle", "Wrapped"));
542 att.Arguments.Add (GetEnumArg ("ParameterStyle", "System.Web.Services.Protocols.SoapParameterStyle", "Bare"));
544 if (outputMembers == null) att.Arguments.Add (GetArg ("OneWay", true));
546 att.Arguments.Add (GetEnumArg ("Use", "System.Web.Services.Description.SoapBindingUse", bodyBinding.Use.ToString()));
549 AddCustomAttribute (method, att, true);
551 CodeTypeDeclaration.Members.Add (method);
553 if (Style == ServiceDescriptionImportStyle.Client) {
554 CodeTypeDeclaration.Members.Add (methodBegin);
555 CodeTypeDeclaration.Members.Add (methodEnd);
561 CodeParameterDeclarationExpression GenerateParameter (XmlMemberMapping member, FieldDirection dir)
564 string type = member.GenerateTypeName (CodeGenerator);
566 string type = member.TypeFullName;
568 CodeParameterDeclarationExpression par = new CodeParameterDeclarationExpression (type, member.MemberName);
573 void GenerateMemberAttributes (XmlMembersMapping members, XmlMemberMapping member, SoapBindingUse use, CodeParameterDeclarationExpression param)
575 if (use == SoapBindingUse.Literal)
576 xmlExporter.AddMappingMetadata (param.CustomAttributes, member, members.Namespace);
578 soapExporter.AddMappingMetadata (param.CustomAttributes, member);
581 void GenerateReturnAttributes (XmlMembersMapping members, XmlMemberMapping member, SoapBindingUse use, CodeMemberMethod method)
583 if (use == SoapBindingUse.Literal)
584 xmlExporter.AddMappingMetadata (method.ReturnTypeCustomAttributes, member, members.Namespace, (member.ElementName != method.Name + "Result"));
586 soapExporter.AddMappingMetadata (method.ReturnTypeCustomAttributes, member, (member.ElementName != method.Name + "Result"));
589 void ImportHeaders (CodeMemberMethod method)
591 foreach (object ob in OperationBinding.Input.Extensions)
593 SoapHeaderBinding hb = ob as SoapHeaderBinding;
594 if (hb == null) continue;
595 if (HasHeader (OperationBinding.Output, hb))
596 ImportHeader (method, hb, SoapHeaderDirection.In | SoapHeaderDirection.Out);
598 ImportHeader (method, hb, SoapHeaderDirection.In);
601 if (OperationBinding.Output == null) return;
603 foreach (object ob in OperationBinding.Output.Extensions)
605 SoapHeaderBinding hb = ob as SoapHeaderBinding;
606 if (hb == null) continue;
607 if (!HasHeader (OperationBinding.Input, hb))
608 ImportHeader (method, hb, SoapHeaderDirection.Out);
612 bool HasHeader (MessageBinding msg, SoapHeaderBinding hb)
614 if (msg == null) return false;
616 foreach (object ob in msg.Extensions)
618 SoapHeaderBinding mhb = ob as SoapHeaderBinding;
619 if ((mhb != null) && (mhb.Message == hb.Message) && (mhb.Part == hb.Part))
625 void ImportHeader (CodeMemberMethod method, SoapHeaderBinding hb, SoapHeaderDirection direction)
627 Message msg = ServiceDescriptions.GetMessage (hb.Message);
628 if (msg == null) throw new InvalidOperationException ("Message " + hb.Message + " not found");
629 MessagePart part = msg.Parts [hb.Part];
630 if (part == null) throw new InvalidOperationException ("Message part " + hb.Part + " not found in message " + hb.Message);
634 if (hb.Use == SoapBindingUse.Literal)
636 map = xmlImporter.ImportDerivedTypeMapping (part.Element, typeof (SoapHeader));
637 hname = part.Element.Name;
638 xmlExporter.ExportTypeMapping (map);
642 map = soapImporter.ImportDerivedTypeMapping (part.Type, typeof (SoapHeader), true);
643 hname = part.Type.Name;
644 soapExporter.ExportTypeMapping (map);
647 string varName = headerVariables [map] as string;
650 if (hname == map.TypeName)
651 varName = memberIds.AddUnique(CodeIdentifier.MakeValid (hname + "Value"),hb);
653 varName = memberIds.AddUnique(CodeIdentifier.MakeValid (hname),hb);
656 string propName = varName;
657 varName = varName + "Field";
659 headerVariables.Add (map, varName);
660 CodeMemberField codeField = new CodeMemberField (map.TypeFullName, varName);
661 CodeTypeDeclaration.Members.Add (codeField);
664 codeField.Attributes = MemberAttributes.Private;
665 CodeMemberProperty codeProperty = new CodeMemberProperty ();
666 codeProperty.Name = propName;
667 codeProperty.Type = new CodeTypeReference (map.TypeFullName);
668 codeProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final;
669 codeProperty.HasGet = codeProperty.HasSet = true;
670 CodeExpression ce = new CodeFieldReferenceExpression (new CodeThisReferenceExpression(), varName);
671 codeProperty.SetStatements.Add (new CodeAssignStatement (ce, new CodePropertySetValueReferenceExpression()));
672 codeProperty.GetStatements.Add (new CodeMethodReturnStatement (ce));
673 CodeTypeDeclaration.Members.Add (codeProperty);
677 codeField.Attributes = MemberAttributes.Public;
681 CodeAttributeDeclaration att = new CodeAttributeDeclaration ("System.Web.Services.Protocols.SoapHeaderAttribute");
682 att.Arguments.Add (GetArg (varName));
684 att.Arguments.Add (GetArg ("Required", false));
686 if (direction != SoapHeaderDirection.In) att.Arguments.Add (GetEnumArg ("Direction", "System.Web.Services.Protocols.SoapHeaderDirection", direction.ToString ()));
687 AddCustomAttribute (method, att, true);
694 internal class Soap12ProtocolImporter : SoapProtocolImporter
696 public override string ProtocolName {
697 get { return "Soap12"; }
700 protected override bool IsBindingSupported ()
702 return Binding.Extensions.Find (typeof(Soap12Binding)) != null;